带有truncate的SQL ROUND()函数取119.1并返回119.09

时间:2015-10-15 13:05:23

标签: sql sql-server casting rounding truncate

我有连续字符串中存储的磅和便士的数据(遗憾的是没有办法解决这个问题),但不能保证2个小数位。

E.g。我的值可能为119.109,因此必须将其翻译为带有截断的2位小数,即119.10,而不是119.11

出于这个原因,我正在避免" CAST为Decimal"因为我不想圆。相反,我使用ROUND(amount, 2, 1)强制截断2位小数。

这在很大程度上起作用,但有时表现出奇怪的行为。例如,119.10输出为119.09。这可以复制为:

ROUND(CAST('119.10' AS varchar),2,1) 

我的目标字段是十进制(19,4)(但是第3和第4个小数位将始终为0,它是一个财务系统,所以总是磅和便士......)。

我认为这个问题与ROUNDing一个varchar有关......但是我不知道如何在没有CAST的情况下知道这个问题,因此引入了这样的舍入方式?

这里发生了什么?

任何想法都非常感激。

1 个答案:

答案 0 :(得分:3)

这是由于浮点数的工作方式,以及您的字符串编号在舍入之前被隐式转换为浮点数的事实。在您的测试用例中:

ROUND(CAST('119.10' AS varchar),2,1)

你隐式地将119.10转换为float,以便它可以传递给ROUND函数,119.10完全不能存储为浮点数,通过运行以下代码证明:

SELECT CAST(CONVERT(FLOAT, '119.10') AS DECIMAL(30, 20))        

返回:

119.09999999999999000000

因此,当你使用truncate进行舍入时,得到119.09。

对于它的价值,你应该always specify a length when converting to, or declaring a varchar