不同精度小数之间的隐式转换

s.d*_*uro 2 sql-server type-conversion

我知道当 SQL Server 处理类型之间的隐式转换时,它将最低优先级转换为最高优先级。

但是当我在不同精度的小数之间执行运算时,结果数据类型是什么?

Pau*_*ite 8

结果的类型由精度、比例和长度 (Transact-SQL) 中规定的规则确定:

下表定义了当运算结果为decimal类型时如何计算结果的精度和小数位数。在以下任一情况下,结果为十进制

  • 两个表达式都是十进制的
  • 一个表达式是小数,另一个是优先级低于小数的数据类型。

操作数表达式表示为表达式 e1,精度为 p1,标度为 s1,表达式 e2,精度为 p2,标度为 s2。任何非十进制表达式的精度和小数位数是为表达式的数据类型定义的精度和小数位数。函数 max(a,b) 的含义如下:取“a”或“b”中较大的值。同理,min(a,b) 表示取“a”或“b”中较小的值。

桌子

* 结果精度和小数位数的绝对最大值为 38。当结果精度大于 38 时,将减少到 38,并减少相应的小数位数,以防止截断结果的整数部分。在某些情况下,例如乘法或除法,不会减少比例因子,以保持小数精度,但可能会增加溢出错误。

在加减运算中,我们需要max(p1 - s1, p2 - s2)位来存储十进制数的整数部分。如果没有足够的空间来存储它们,即 ,max(p1 - s1, p2 - s2) < min(38, precision) - scale则缩小比例以提供足够的空间来容纳整体部分。结果比例为MIN(precision, 38) - max(p1 - s1, p2 - s2),因此小数部分可能会四舍五入以适应结果比例。

查看结果类型的一种方便快捷的方法是使用SQL_VARIANT_PROPERTY

DECLARE @V1 decimal (9, 6) = 123.456789;
DECLARE @V2 decimal (7, 2) = 12345.67;

SELECT 
    [BaseType] = SQL_VARIANT_PROPERTY(@V1 + @V2, 'BaseType'),
    [Precision] = SQL_VARIANT_PROPERTY(@V1 + @V2, 'Precision'),
    [Scale] = SQL_VARIANT_PROPERTY(@V1 + @V2, 'Scale');
Run Code Online (Sandbox Code Playgroud)

输出:

DECLARE @V1 decimal (9, 6) = 123.456789;
DECLARE @V2 decimal (7, 2) = 12345.67;

SELECT 
    [BaseType] = SQL_VARIANT_PROPERTY(@V1 + @V2, 'BaseType'),
    [Precision] = SQL_VARIANT_PROPERTY(@V1 + @V2, 'Precision'),
    [Scale] = SQL_VARIANT_PROPERTY(@V1 + @V2, 'Scale');
Run Code Online (Sandbox Code Playgroud)

db<>小提琴演示