我知道这是一个很老的问题,但现有的答案似乎都没有解决“为什么?” 你的问题的方面。
首先,您的文字表达式的数据类型是什么?我不确定(也没有查)所以我运行了以下命令:
select 1.4 union all
select 'frob'
返回错误:
消息 8114,级别 16,状态 5,第 1
行将数据类型 varchar 转换为数字时出错。
好的,所以1.4
和其他文字是numeric
- aka decimal
。
接下来,SUM
如果传递了decimal(p,s)
1 ,函数的返回类型是什么:
十进制(38, s)
好的,所以SUM
查询中 3 个表达式的数据类型是decimal(38,1)
,decimal(38,4)
和decimal(38,2)
. 鉴于这 3 种数据类型可供选择,decimal(38,1)
最终选择的类型是基于不同精度和比例的规则。
结果精度和小数位数的绝对最大值为 38。当结果精度大于 38 时,相应的小数位数会减小,以防止结果的整数部分被截断。
所以,最后,回到文档decimal
:
默认情况下,SQL Server 在将数字转换为精度和小数位数较低的小数或数值时使用舍入。但是,如果 SET ARITHABORT 选项为 ON,则 SQL Server 会在发生溢出时引发错误。仅损失精度和规模不足以引发错误。
所以这就是你的最终结果。
1起初,这种类型可能看起来令人惊讶,直到您意识到通常sum
会针对多行进行操作,并且给定精度和比例的多个值很容易溢出它们自己的数据类型。decimal(38,s)
为特定 SUM()
事件提供最大可能的空间来容纳任何溢出而不会丢失任何精度,并且意味着可以在查询执行之前决定最终数据类型。