1. 问题重现
最近线上出了个问题,用户明明没有投票,却提示已投票,我查询数据,刚开始没有查出数据,后来却查出数据了,以为没有问题,后来以为是插入的时候通过int类型插入,导致varchar类型的索引没有添加这条索引(天真的想法),再后来看到查出来的数据和我查询的数据并不一致,最后一位不太相同,知道应该是发生了mysql隐式转化问题。
接下来就来研究下不加引号或者加引号的情况。
2. 问题探讨
先看看数据结构:
- id为数字型
- name为字符串类型
测试数据:
2.1 varchar字段查询:
- 可以看出通过123456789123456788也能查出123456789123456789的数据。
2. 可以看出123456789123456777也查出结果了。3. 可以看出123456789123456666并没有查出结果,这里我们可以分析出,数字转为字符串的时候,有效位是16位。
- 可以看出12345678912345678也没有查出结果,说明长度不一致也不能查出结果,所以我觉得数字转字符串如果超出16位,后面是用占位符代替的,类似like中的占位符。
2.2 int类型字段查询
- 可以看出通过’1aaa’也能查出数字类型的1
- 但是’11’是不可以的。
3. mysql隐式转化:
隐式类型转换规则:
- 如果一个或两个参数均为NULL,则比较的结果为NULL,除了 相等比较运算符。对于NULL NULL,结果为true。
- 如果比较操作中的两个参数都是字符串,则将它们作为字符串进行比较。
- 如果两个参数都是整数,则将它们作为整数进行比较。
- 如果不与数字比较,则将十六进制值视为二进制字符串。
- 如果参数之一是 timestamp 或 datatime column,而另一个参数是常量,则在执行比较之前,该常量将转换为时间戳。
- 如果参数之一是十进制值,则比较取决于另一个参数。如果另一个参数是十进制或整数值,则将参数作为十进制值进行比较;如果另一个参数是浮点值,则将参数作为浮点值进行比较。
- 在所有其他情况下,将参数作为浮点数(实数)进行比较。例如,将字符串和数字操作数进行比较,将其作为浮点数的比较。
3.1 测试:
从结果可以看出,在字符串和int比较时,字符串会被隐式转换为0值