SQL server 2005数值精度损失

Ily*_*hin 5 sql-server floating-point casting type-conversion floating-accuracy

调试一些与财务相关的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以这种方式运行以及我的样本中实际发生了哪种类型的转换?

Eug*_*ota 7

正如浮点类型的添加不准确一样,如果超出精度,则十进制类型的乘法可能不准确(或导致不准确).请参见数据类型转换以及十进制和数字.

既然你乘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
Run Code Online (Sandbox Code Playgroud)

减少到

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
Run Code Online (Sandbox Code Playgroud)

再次,在NUMERIC(24,8)和之间NUMERIC(38,6),SQL Server将尝试保存潜在的32位非小数,因此A + D减少到

SELECT CAST(0.12345678 AS NUMERIC(38,6))
Run Code Online (Sandbox Code Playgroud)

0.123457四舍五入后给你.