在SQL Server中划分十进制类型会导致不必要的尾随零

时间:2014-11-20 17:31:09

标签: sql-server tsql decimal type-conversion sqldatatypes

当我发现一些奇怪的行为时,我在SQL Server中执行了一些简单的财务计算。我试图将一串数字转换为十进制类型。虽然字符串不包含小数点,但我从我的规范中知道字符串中的最后3个位置应该在小数点后面。

我的第一种方法存在缺陷,但是这样做了:

select convert(decimal(11,3),89456123/1000) as TotalUnits

这导致 89456.000 。在演员表演之前执行除法导致小数部分被截断。

所以我把分裂操作移到了演员之外,就像这样:

select convert(decimal(11,3),89456123)/1000 as TotalUnits

这导致小数点后的位置爆炸。它返回 89456.12300000

根据我的十进制规格,我想要11位数,其中3位在小数点后面。现在我有13位总数,其中8位小数点后面。发生了什么事?

为了得到我想要的东西,我想我必须加倍演员,就像这样:

select convert(decimal(11,3), convert(decimal(11,3),89456123)/1000)

,提供 89456.123

事实证明,无论我除以什么,产生的小数点爆炸都是一样的。是否将数据类型转换为double或者什么?

我的问题是: 为什么会发生这种情况,并且有一种更优雅的方式来补偿它,而不是双重转换为十进制。

修改 我在SO上找到了similar question,但看起来它们又是双重投射。

3 个答案:

答案 0 :(得分:2)

SQL server执行整数运算,强制它使用数字,你可以将它乘以1.0

无需使用转换两次。这使89456.123无法进行双重转换。

select convert(decimal(11,3),89456123*1.0/1000) as TotalUnits

答案 1 :(得分:2)

为什么convert(decimal(11,3),89456123)/1000以小数点后6位结尾?规则要求它。 numeric division has rather complicated rules about the resulting type

当您说1.0时,您最终会得到一个数字,其中最小比例因子可能代表此值:

SELECT SQL_VARIANT_PROPERTY(1.11, 'BaseType')
SELECT SQL_VARIANT_PROPERTY(1.11, 'Precision')
SELECT SQL_VARIANT_PROPERTY(1.11, 'Scale')
SELECT SQL_VARIANT_PROPERTY(1.11, 'TotalBytes')

你应该怎么做?我认为由于复杂的规则,没有真正优雅的解决方案。我能想到的任何解决方案都涉及中间结果的相当疯狂的类型推断。我推荐几乎与RADAR相同的解决方案:

select convert(decimal(11,3), convert(decimal(11, 3), 89456123)/1000) as TotalUnits

主要区别在于我认为*1.0"技巧"用作演员的简写是混淆代码的含义。如果您碰巧喜欢它,请随意使用它。

答案 2 :(得分:0)

select convert(decimal(11,3),89456123/CONVERT(decimal(11,3),1000))