调试一些与财务相关的SQL代码时,发现了一个数字(24,8)数学精度的奇怪问题。
在您的MSSQL上运行以下查询,您将获得A + B * C表达式结果为0.123457
从(SELECT CAST(0.12345678 AS NUMERIC(24,8))AS A,CAST(0 AS NUMERIC(24,8))AS B,CAST(500 AS NUMERIC(24)选择SELECT A,B,C,A + B * C ,8))AS C)T
因此,我们丢失了2个重要符号。尝试以不同的方式解决此问题,我得到了将中间乘法结果(为零!)转换为数值(24,8)的效果。
最后一个解决方案。但是我仍然有一个问题-为什么MSSQL会以这种方式运行,并且样本中实际上发生了哪种类型转换?
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
正如浮点类型的加法不准确一样,如果超出精度,则十进制类型的乘积可能不准确(或导致不准确)。请参阅数据类型转换以及十进制和数字。
由于您将NUMERIC(24,8)和相乘NUMERIC(24,8),并且SQL Server将仅检查类型而不是内容,因此当它无法保存所有48位精度(最大为38)时,它可能会尝试保存潜在的16位非十进制数字(24-8) )。将它们中的两个结合起来,您将获得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四舍五入后。