Gha*_*eak 4 mysql floating-point precision comparison casting
我在本地安装了MySQL,运行时SELECT VERSION()返回此值:5.6.43-84.3
当我运行查询时,它只返回1行时返回多行。让我对其进行设置,以这种方式更容易解释。
CREATE TABLE test_table
(
test_val VARCHAR(255)
)
;
INSERT INTO test_table (test_val)
VALUES
('9671986020630615'),
('9671986020630616'),
('9671986020630617')
;
运行以下查询(此查询返回预期的1行):
SELECT *
FROMtest_table
WHEREtest_val= '9671986020630615'
;
运行此查询(此查询返回3行,不应返回):
SELECT *
FROMtest_table
WHEREtest_val= 9671986020630615
;
这是我对这种情况的观察:
WHERE用单引号将子句中的值引起来。WHERE子句中的值周围包含单个tic。VARCHAR(255)WHERE子句中的字符串与测试表(VARCHAR(255))中的字符串值进行比较WHERE第二个查询子句中的数值与测试表(VARCHAR(255))中的字符串值进行比较时,发生了某种情况,这导致MySQL返回3行而不是仅返回1行。第一个查询返回正确的结果是有意义的,因为它正在将字符串与字符串进行比较。
从某种意义上说,第二个查询正在返回错误的数据集(3行,而不是应该返回的1行)。
但是我的问题是为什么 MySQL会这样做?为什么当将一个数字与3个不同的VARCHAR(255)值进行比较时,如果WHERE子句中数值的真实值仅匹配1行,它会返回所有3行?
因此,实质上,对于第一个查询,MySQL就是这样说的:
'9671986020630615'='9671986020630615',
'9671986020630615'<>'9671986020630616',
'9671986020630615'<>'9671986020630617'
但是对于第二个查询,它说:
9671986020630615 ='9671986020630615',
9671986020630615 ='9671986020630616',
9671986020630615 ='9671986020630617'
任何帮助都感激不尽。
MySQL使用IEEE双精度浮点表示法,内部处理所有数字的方式与Javascript相同。
当您省略长数字字符串中的引号时,即您用9671986020630615代替'9671986020630615 ',MySQL将使用该数字。然后,当它运行WHERE查询的一部分时,它会默默地将每个列值强制为双精度数字。
但是由于机器epsilon(精度极限)的双重精度,9671986020630615、9671986020630616和9671986020630617都具有相同的值。因此,WHERE会找到所有这三个。
CAST(9671986020630615 AS DOUBLE) CAST(9671986020630616 AS DOUBLE) CAST(9671986020630617 AS DOUBLE)
9.671986020630616e15 9.671986020630616e15 9.671986020630616e15 |
Run Code Online (Sandbox Code Playgroud)
看到所有三个整数如何具有与DOUBLE相同的表示吗?