mysql隐式转换
create table testSql(id int(11),name varchar(11),descid varchar(11));
alter table testSql add index(descid) alter table testSql add
unique(id) insert into testSql
values(1,‘123’,‘1’),(2,‘123a’,‘2’),(3,‘639’,‘3’) select * from
testSql;tablename: testSql fieldName:id,name,descid
什么是隐式转换
在mysql查询中,当查询条件左右两侧的类型不匹配就会发生隐式转换;常见的比如 varchar 转化为 int 如下面的查询
select * from testSql where name = 123
实际运行的时候,会把上面的 sql语句转化为:
select * from testSql where cast(name as signed int) = 123
隐式转换可能引发的问题,缺点
如果隐式转换在索引列,那么该索引失效,效率大大降低!
示列:
explain select * from testSql where descid = 1
explain select * from testSql where descid = '1'
分析第一行,sql 没有走索引:因为查询条件左右两边的数据类型不匹配 descid 发生了 隐式转换 。使用了cast函数进行转换,一旦对索引字段使用函数操作,mysql将放弃使用索引。
但是当对主键使用上述操作时:
explain select * from testSql where id = 1
explain select * from testSql where id = '1'
是都会走索引查询的,这是为什么呢?
因为 int 类型的数字只有1能转化为’1’,是唯一确定的。所以虽然需要隐式转换,但不影响使用索引
常见的隐式转换
1, 两个参数至少有一个是 NULL 时,比较的结果也是 NULL,例外是使用 <=>
对两个 NULL 做比较时会返回 1,这两种情况都不需要做类型转换
2, 两个参数都是字符串,会按照字符串来比较,不做类型转换
3, 两个参数都是整数,按照整数来比较,不做类型转换
4, 十六进制的值和非数字做比较时,会被当做二进制串
5, 有一个参数是 TIMESTAMP 或 DATETIME,并且另外一个参数是常量,常量会被转换为 timestamp
6, 有一个参数是 decimal 类型,如果另外一个参数是 decimal 或者整数会将整数转换为 decimal 后进行比较,
如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较
7, 所有其他情况下,两个参数都会被转换为浮点数再进行比较
隐式转换的坑
其实我预期效果应该是 第一条,但是第二条也显示出来了。我们在update delete 处理的时候 ,可能会发现自己不小心 有多删一条,或者多修改一条 可以检查一下是否是上述的原因
总结
- 写完sql 记得 explain 看一下执行计划是否走索引
- 查询条件两边的类型要一致;发生类型转化可能会造成误操作
如何看懂explain:
https://blog.csdn.net/hollis_chuang/article/details/106368688
参考文章为:
https://mp.weixin.qq.com/s/5HMyBGrOMUXytmPAhgwAgQ
本文地址:https://blog.csdn.net/lin2535290272/article/details/107641818