SQL 带截断的 ROUND() 函数需要 119.1 和 returns 119.09

SQL ROUND() function with truncate takes 119.1 and returns 119.09

我将英镑和便士的数据存储在连接的字符串中(不幸的是,没有办法解决这个问题)但不能保证小数点后两位。

例如我可能会得到 119.109 的值,因此必须截断后将其转换为小数点后 2 位,即 119.10,而不是 119.11.

出于这个原因,我避免 "CAST as Decimal" 因为我不想四舍五入。相反,我使用 ROUND(amount, 2, 1) 强制截断小数点后 2 位。

这在大多数情况下都有效,但有时会表现出奇怪的行为。例如,119.10 输出为 119.09。这可以复制为:

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

我的目标字段是 Decimal(19,4)(但是第三和第四位小数总是 0,这是一个金融系统所以总是英镑和便士...)。

我认为问题与对 varchar 进行舍入有关....但我不知道如何解决这个问题而不必 CAST 因此以这种方式引入舍入?

这里发生了什么?

非常感谢任何想法。

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

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

您正在隐式地将 119.10 转换为浮点数,以便它可以传递给 ROUND 函数,119.10 完全不能存储为浮点数,运行 证明如下:

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

哪个returns:

119.09999999999999000000

因此,当您使用 truncate 对其进行舍入时,您将得到 119.09。

物有所值,你应该always specify a length when converting to, or declaring a varchar