【发布时间】:2018-03-26 18:31:55
【问题描述】:
开发人员已联系我询问舍入问题。
我们计划将我们的数据库迁移到 SQL Server 2016,在新的 SQL 平台测试期间,我们发现 SQL Server 2016 在四舍五入方面比预期的差一点。
这种差异似乎是在更改/设置更高的兼容性级别时更改默认舍入方法的结果。
--SQL Server 2016 数据库兼容模式130
declare @a float = -0.0051175 -- 7 digits
declare @b float = 0.0051175
select round(@a, 6), round(@b, 6)
Result
------------------------------------
-0.005117 , 0.005117
--兼容模式100的SQL Server 2016数据库
declare @a float = -0.0051175 -- 7 digits
declare @b float = 0.0051175
select round(@a, 6), round(@b, 6)
Result
-----------------------------------
-0.005118 , 0.005118
有人对此有什么想法吗?
【问题讨论】:
-
如果您真的担心数据的准确性,您应该停止使用浮点数。它不是一个精确的数据类型,并且会发生舍入错误。改用小数,那些舍入错误将不再发生。
-
兼容级别 110 也是
-0.005118, 0.005118 -
谢谢,我才意识到这一点。在兼容级别 120 之前,它会按照我们预期的方式工作,然后随着 130 的变化而变化。
-
2016 年优化器发生了重大变化,因此并不完全出乎意料。常量的表示在两个兼容级别下都是相同的,并且与 C# 加载的内容相同 (
0x3F74F61672324C83),因此受到影响的是ROUND,其确切算法没有记录。 FP 处理中有documented changes,但这不是记录在案的更改之一(并且跟踪标志 139 无效)。请注意,ROUND(0.0051175000000000005e, 6)是“正确的”(0.0051175000000000005e是下一个FLOAT)。 -
值得一提的是,常量转换为的
FLOAT比0.0051175略小(所以它更像0.00511749999..),所以在某种意义上ROUND是“正确的”。在另一种意义上,它不是——这完全取决于你如何准确地定义操作,而文档仔细没有做到这一点。
标签: sql sql-server tsql sql-server-2016 database-administration