MySQL中字符串与数字比较的坑之二

上一篇文章是转载的,主要说了MySQL字符串转数值的一些坑,然而,并没有解决我遇到的问题,试了几个小时终于发现了些端倪,简单记录一下。

我在排查问题的时候,用Navicat查询数据库,本该是字符串的地方我写成了数值,结果诡异的情况发生了:

MySQL中字符串与数字比较的坑之二

按照上一篇文章的说法,字符串转数值会截取第一个非数字前面的数字,按照这个说法,这个数值应该是2892000120000020275才对,那么应该只有一条记录被查出来,但是这里却查出了3条,所以应该还有一些小秘密没有被发现。

接下来直接用select语句判断两个值是否相等,发现在一定的范围内,两个值都是相等的:

以字符串“2892000120000020283”为例,在值为2892000120000020224~2892000120000020736之间时都是相等

MySQL中字符串与数字比较的坑之二MySQL中字符串与数字比较的坑之二

也就是说在一定范围内,字符串的取值都是一样的,还有这种操作?

那么让我们在回到上一篇文章,字符串转换成数字是截取第一个非数字前的所有数字来作为值的,那么图中的字符串其实是整个都被转化了,让我们来看看转化字符串的方法有哪些。

方法一:SELECT CAST('2892000120000020283' AS SIGNED);
方法二:SELECT CONVERT('2892000120000020283',SIGNED);
方法三:SELECT '2892000120000020283'+0;
前两种方法都很明确的将字符串转换成了数值,并且再进行上面图中比较的时候,不会出现稀奇古怪相等的情况,那么,我们来看看第三种情况将字符串转换成了什么。

MySQL中字符串与数字比较的坑之二

诶?出现了奇怪的东西!没错,科学计数法!!

根据前面的测试结果猜测,2892000120000020224~2892000120000020736之间的科学计数法可能是一样的,因此导致了这一系列的“数值”都相等。

以下取两个临界值2892000120000020224和2892000120000020223来转换,结果如下:

MySQL中字符串与数字比较的坑之二MySQL中字符串与数字比较的坑之二

可以看到两个临界值的科学计数法发生了改变,另外两个同理,而在这之间的值,其科学计数法的值都是一样的。

由此得出结论,MySQL的字符串转换用的其实是第三种方法,当字符串所能表示的数值大于某值后,第三种转换方式需要用科学计数法表示,但是导致在一定范围内的值取值都一样,这样会使查询结果不可预期,但是即便值可以正常转换,请不要使用数值来和字符串进行比较,就好像你能将灯泡放进嘴里,但请别那么做!!

另外,字符串和数字比较是自反的,也就是说select 字符串 = 数值 与 select 数值 = 字符串结果是一样的。