MySQL返回与搜索条件不匹配的多行

MySQL returning multiple rows that does not match search criteria

提问人:Gharbad The Weak 提问时间:6/7/2019 最后编辑:CommunityGharbad The Weak 更新时间:12/3/2019 访问量:402

问:

我在本地安装了MySQL,运行返回此值:SELECT VERSION()5.6.43-84.3

当我运行查询时,它应该只返回 1 行,但它返回多行。让我设置一下,这样解释起来更容易。

  1. 创建测试表:
    CREATE TABLE test_table 
    (
        test_val VARCHAR(255)
    )
    ;
  1. 将 3 个值加载到表中:
    INSERT INTO test_table (test_val)
    VALUES 
    ('9671986020630615'),
    ('9671986020630616'),
    ('9671986020630617')
    ;
  1. 运行此查询(此查询返回预期的 1 行):
    SELECT * 
    FROM test_table
    WHERE test_val = '9671986020630615'
    ;
  1. 运行此查询(此查询返回 3 行,它不应该):
    SELECT * 
    FROM test_table
    WHERE test_val = 9671986020630615
    ;

以下是我对这种情况的观察:

  1. 第一个查询用单引号将子句中的值括起来。WHERE
  2. 第二个查询不会用单个 tic 将子句中的值括起来。WHERE
  3. 测试表中的列定义为VARCHAR(255)
  4. 第一个查询只返回一行是有道理的,因为它将子句中的字符串与测试表中的字符串值进行比较 (WHEREVARCHAR(255))
  5. 当MySQL将第二个查询的子句中的数值与测试表()中的字符串值进行比较时,会发生一些事情,这导致MySQL返回3行,而不仅仅是1行。WHEREVARCHAR(255)

第一个查询返回正确的结果是有意义的,因为它将字符串与字符串进行比较。

第二个查询返回一个错误的数据集(3 行,而不是它应该返回的 1 行)也在一定程度上是有道理的。

但我的问题是MySQL为什么要这样做?为什么当它将一个数字与 3 个不同的值进行比较时,当子句中数值的真实值仅匹配 1 行时,它会返回所有 3 行?VARCHAR(255)WHERE

因此,从本质上讲,对于第一个查询,MySQL是这样说的:

'9671986020630615' = '9671986020630615',

“9671986020630615”<>“9671986020630616”,

“9671986020630615”<>“9671986020630617”

但对于第二个查询,它说:

9671986020630615 = '9671986020630615',

9671986020630615 = '9671986020630616',

9671986020630615 = '9671986020630617'

任何帮助将不胜感激。

MySQL 强制转换 浮点 比较 精度

评论

1赞 Uueerdo 6/7/2019
我的猜测是MySQL试图将它们都解释为INT(不是BIGINT),并且由于INT无法保存这些值,因此它们最终是相同的值。使用 sql fiddle 显示测试表中所有行的选择和结果。CAST(9671986020630615 AS SIGNED)CAST(test_val AS SIGNED)9671986020630616
0赞 Gharbad The Weak 6/7/2019
@Uueerdo把它作为答案发布,我会给你并投赞成票。是的,当我遇到这个时,我周围没有人。自从我发布这个问题以来,我在工作中问过一些人,这基本上就是他们所说的,这与MySQL在将数字与字符串进行比较时不支持超过10位左右的数字有关。
1赞 Uueerdo 6/7/2019
就跟着琼斯一起去吧,看起来他们研究得很正确,而不仅仅是猜测。
0赞 Gharbad The Weak 6/7/2019
@Uueerdo,您是一位绅士(或绅士)和学者,我很欣赏您的亲切。再次感谢。

答:

5赞 O. Jones 6/7/2019 #1

MySQL在内部处理所有数字的方式与Javascript相同,具有IEEE双精度浮点表示

当您从长数字字符串中省略引号时,即您写代替 ,MySQL 使用该数字。然后,当它运行查询的一部分时,它会以静默方式将每个列值强制转换为双精度数字。9671986020630615'9671986020630615 'WHERE

但是由于机器的epsilon(精度的极限)的双精度,9671986020630615、9671986020630616和9671986020630617都具有相同的值。所以 WHERE 找到了这三个。

CAST(9671986020630615 AS DOUBLE) CAST(9671986020630616 AS DOUBLE) CAST(9671986020630617 AS DOUBLE) 
     9.671986020630616e15             9.671986020630616e15             9.671986020630616e15 | 

看看这三个整数如何与 DOUBLE 具有相同的表示形式?

评论

0赞 Gharbad The Weak 6/7/2019
非常感谢您快速、准确和具体的回答。点赞并被接受为答案。
1赞 jlp 6/7/2019
mysql 文档中的此页面正好讨论了这个问题: dev.mysql.com/doc/refman/5.6/en/type-conversion.html