![058bca87e6c63f41648f2ff4a8f34203.png](https://i-blog.csdnimg.cn/blog_migrate/3743e0bf505184b81cc48f53a59610a7.jpeg)
“数据库里明明没有符合条件的数据,为什么结果还是有数据返回”,最近好几个同事差一点被这个问题难住了。
事情是这样的,前几天,一个在生产环境运行了好几个月的功能在测试环境调试发生了一个异常,也就是数据库里明明没有某个用户的数据,但在实际查询时却返回了一些无关数据,导致一个本来应该判断为空的逻辑,结果判断为不为空。
定位了好久,后来终于找到了问题所在。原来,就是下面这个SQL查询语句出现了问题。
![8d14680ed21de264aa9cac8d599c52e1.png](https://i-blog.csdnimg.cn/blog_migrate/ed0186dc8e5178707f742cfbcb4ef467.jpeg)
结合上面的SQL语句和下面的表结构,大家也可以思考思考,如果让你来执行这个SQL,你能预知结果吗?为什么?
![7e4845c59c58ca6367673cb74df90241.png](https://i-blog.csdnimg.cn/blog_migrate/66ef7aeaae7d6c4c98e2a1ce21c70741.jpeg)
相信很多人会认为,这结果就是空,但实际呢?
![f42da0d6d4859baa42831b53dd5b67a5.png](https://i-blog.csdnimg.cn/blog_migrate/8cb582281e1213adac3dc5e241f11dfb.jpeg)
实际上,如上图所示,结果不为空。
要解释这样的结果,那就不得不说MySQL中数据类型的隐式转换。
在MySQL中,当操作符与不同类型的操作数一起使用时,会发生类型隐式转换以使操作数兼容。在MySQL中,数据类型隐式转换的规则主要有以下几条:
- 两个参数至少有一个是 NULL 时,比较的结果也是 NULL,例外是使用 <=> 对两个 NULL 做比较时会返回 1,这两种情况都不需要做类型转换
- 两个参数都是字符串,会按照字符串来比较,不做类型转换
- 两个参数都是整数,按照整数来比较,不做类型转换
- 十六进制的值和非数字做比较时,会被当做二进制串
- 有一个参数是 TIMESTAMP 或 DATETIME,并且另外一个参数是常量,常量会被转换为 timestamp
- 有一个参数是 decimal 类型,如果另外一个参数是 decimal 或者整数,会将整数转换为 decimal 后进行比较,如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较
- 所有其他情况下,两个参数都会被转换为浮点数再进行比较
前面提到的执行异常的SQL查询语句,满足第7条,也就是name和false会被先转换成浮点数,然后再做比较。
在Mysql中,以数字开头的字符串,转换成浮点数时,会直接使用开头的数字;而不是以数字开头的字符串,转换成浮点数时,会直接变成0。如下:
![205ce999f75921db96901e2574148f0b.png](https://i-blog.csdnimg.cn/blog_migrate/2c5aa04ede1602c2a70eb61c60439db8.jpeg)
至于bool值,false转换成浮点型会变成0,true转换成浮点型会变成1。如下:
![7abdfc1224910788a25bc40d90aae574.png](https://i-blog.csdnimg.cn/blog_migrate/c5d39b92525251b5635ddce2e56afc42.jpeg)
这样一来,原来的SQL语句,在实际执行时就变成了下面这样:
![9d421ca9d7aaa92da81f33a3229bdf46.png](https://i-blog.csdnimg.cn/blog_migrate/29a0d55fb74e158f5fe8418cc4cf9797.jpeg)
如此一来,当然就可以查出数据来呀。唉,真是“一文钱难倒英雄汉”。
以后写SQL查询语句时,一定要确保查询条件的类型与数据库对应字段类型是一致的。