【发布时间】:2015-04-27 04:17:00
【问题描述】:
在 MySQL 上的第一个查询有什么问题?
两列的预期答案是“718042670591505846”
SELECT 5002622390 + (5102 * 140737488355328) new_iid_hard_way,
CAST(5002622390 + (5102 * POWER(2,47)) AS UNSIGNED) new_iid_WRONG_way
返回:
'718042670591505846','718042670591505792'
同时,此查询有效:
SELECT 5002622390 + (5102 * 140737488355328) new_iid_hard_way,
5002622390 + (5102 * CAST(POWER(2,47) AS UNSIGNED)) new_iid_CORRECT_way
它返回: '718042670591505846', '718042670591505846'
我的预感是这是一个数据类型溢出/包装问题...但即使在 MySQL 5.6.15 上启用了严格模式,我也没有收到任何错误。
有趣的是,sqlfiddle 在所有 4 种情况下都会出错:
http://sqlfiddle.com/#!9/d1bb6/1
返回 718042670591505800
这是溢出问题吗?如果是,为什么启用严格模式时 MySQL 不报错?
【问题讨论】:
-
根据我的经验,Mysql 更喜欢做错事,尽可能不返回错误。我想知道其他数据库是否也会出现同样的问题
-
我认为您可以通过表达式 (5102 * POWER(2,47) 到浮点类型进行隐式数据类型转换,并在进行强制转换之前在加法中失去精度。看看
SELECT CAST(5102 * POWER(2, 47) AS UNSIGNED), 5102 * POWER(2, 47); -
并且没有溢出,因为没有定义数据类型的列。
-
在此处查看我的答案:stackoverflow.com/questions/24442089/… 用于 Javascript,但我怀疑此处涉及类似问题。
-
@Barmar 有趣的是,不同的机器得到不同的结果。在带有 MySQL 5.6.6 的 sqlfiddle 上(正如它所说),演员表根本没有任何区别,在我的带有 MySQL 5.6.16 的 Windows 8.1 64 位计算机上(根本没有太大区别)我可以重现问题。