检查发票里的金额税额计算SQL的时候,发现金额、税额四舍五入为2位小数的结果,有的有进位,有的没有进位。
最后检查出其中一个计算变量是float类型,乘了以后再四舍五入必出异常。
重现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
DECLARE @i1 float=1000.025000 , @i2 float=256.025000 , @i3 float=255.025000 , @i4 float=3.025000 , @i5 float=0.025000 SELECT 'ROUND float',ROUND(@i1,2),ROUND(@i2,2),ROUND(@i3,2),ROUND(@i4,2),ROUND(@i5,2) DECLARE @f1 float(53)=1000.025000 , @f2 float(53)=256.025000 , @f3 float(53)=255.025000 , @f4 float(53)=3.025000 , @f5 float(53)=0.025000 SELECT 'ROUND float(53)',ROUND(@f1,2),ROUND(@f2,2),ROUND(@f3,2),ROUND(@f4,2),ROUND(@f5,2) DECLARE @d1 float(10)=1000.025000 , @d2 float(10)=256.025000 , @d3 float(10)=255.025000 , @d4 float(10)=3.025000 , @d5 float(10)=0.025000 SELECT 'ROUND float(10)',ROUND(@d1,2),ROUND(@d2,2),ROUND(@d3,2),ROUND(@d4,2),ROUND(@d5,2) |
1 2 3 4 5 6 7 |
输出结果: ROUND float 1000.02 256.02 255.03 3.02 0.03 ROUND float(53) 1000.02 256.02 255.03 3.02 0.03 ROUND float(10) 1000.03 256.02 255.02 3.03 0.03 |
变量数字大小不同,进位结果不同;定义变量为不同的float精度,进位结果不同。
解决办法:
将变量改为dec类型
1 2 3 4 5 6 |
DECLARE @d1 dec(28,10)=1000.025000 , @d2 dec(28,10)=256.025000 , @d3 dec(28,10)=255.025000 , @d4 dec(28,10)=3.025000 , @d5 dec(28,10)=0.025000 SELECT 'ROUND float(10)',ROUND(@d1,2),ROUND(@d2,2),ROUND(@d3,2),ROUND(@d4,2),ROUND(@d5,2) |
输出结果:
ROUND dec 1000.0300000000 256.0300000000 255.0300000000 3.0300000000 0.0300000000
________________________________
原因:
在SQL Server中,实际上小数数值只有两种数据类型:float 和 decimal,分别是近似数值和精确数值。其他小数类型,都可以使用float和decimal来替代,例如,双精度(double precision)数据类型等价于 float(53),real等价于float(24),numeric是 decimal的同义词,应该避免在程序中直接使用 double precision、real和numeric,而是用 float(24) 、float(53)和decimal 代替。
float是近似数值,存在精度缺失;decimal是精确数值,不存在精度损失。当数值不允许精度丢失时,使用 decimal数据类型存储数据。在计算小数的除法时,SQL Server 内部隐式升级数据类型,根据小数数值的数据类型,就近向float(24) 或float(53)转换。
© 2018, ITJOY.NET. 版权所有. 如未注明,均为原创,转载请注明出处。