调试一些与财务相关的SQL代码发现了数学(24,8)数学精度的奇怪问题.
在MSSQL上运行以下查询,您将获得A + B*C表达式结果为0.123457
SELECT A,B,C,A + B*C FROM(选择CAST(0.12345678 AS NUMERIC(24,8))AS A,CAST(0 AS NUMERIC(24,8))AS B,CAST(500 AS NUMERIC(24) ,8))AS C)T
所以我们失去了两个重要的符号.试图以不同的方式解决这个问题,我将中间乘法结果(即Zero!)转换为数字(24,8),这样可以正常工作.
最后一个有解决方案.但是我还有一个问题 - 为什么MSSQL以这种方式运行以及我的样本中实际发生了哪种类型的转换?
正如浮点类型的添加不准确一样,如果超出精度,则十进制类型的乘法可能不准确(或导致不准确).请参见数据类型转换以及十进制和数字.
既然你乘NUMERIC(24,8)
和NUMERIC(24,8)
,和SQL Server将只检查不类型的内容,它可能会尝试保存潜在的16个非十进制数字(24 - 8),当它不能保存的精度所有48个位数(最多为38 ).结合其中两个,你得到32个非十进制数字,只留下6位十进制数字(38 - 32).
因此原始查询
SELECT A, B, C, A + B * C FROM ( SELECT CAST(0.12345678 AS NUMERIC(24,8)) AS A, CAST(0 AS NUMERIC(24,8)) AS B, CAST(500 AS NUMERIC(24,8)) AS C ) T
减少到
SELECT A, B, C, A + D FROM ( SELECT CAST(0.12345678 AS NUMERIC(24,8)) AS A, CAST(0 AS NUMERIC(24,8)) AS B, CAST(500 AS NUMERIC(24,8)) AS C, CAST(0 AS NUMERIC(38,6)) AS D ) T
再次,在NUMERIC(24,8)
和之间NUMERIC(38,6)
,SQL Server将尝试保存潜在的32位非小数,因此A + D
减少到
SELECT CAST(0.12345678 AS NUMERIC(38,6))
0.123457
四舍五入后给你.