T-SQL中数值类型的优先级

时间:2014-09-24 16:48:20

标签: sql sql-server tsql

关于T-SQL使用type precedence表达式中使用的各种numeric类型处理CASE的方式,我完全是一棵树。你能用下面的测试来解释一下:

-- Consider the query:
SELECT
CASE
        WHEN 1=1 THEN CAST(1.555 AS numeric(16,3))
        ELSE  CEILING((1+1) * CAST(1 AS Numeric(16,2)) * CAST(1 AS int))
END AS Test
-- This returns 2 (scale = 0)
-- Now, remove the CEILING function:
SELECT
CASE
        WHEN 1=1 THEN CAST(1.555 AS numeric(16,3))
        ELSE  (1+1) * CAST(1 AS Numeric(16,2)) * CAST(1 AS int)
END AS Test
-- and it gives 1.56 (scale = 2)
-- Now replace (1+1) with 2:
SELECT
CASE
        WHEN 1=1 THEN CAST(1.555 AS numeric(16,3))
        ELSE  (2) * CAST(1 AS Numeric(16,2)) * CAST(1 AS int)
END AS Test
-- and it yields 1.555 (scale = 3)

我似乎不对,因为numeric(16,3)分支中的所有三个查询1=1都应该优先于ELSE分支的不太精确的结果。

1 个答案:

答案 0 :(得分:4)

问题是案例的第二个分支在每种情况下都有不同的数据类型。

SELECT CAST(1.555 AS NUMERIC(16, 3))                                   AS A,
       CEILING(( 1 + 1 ) * CAST(1 AS NUMERIC(16, 2)) * CAST(1 AS INT)) AS B,--NUMERIC(38,0)
       CAST(1.555 AS NUMERIC(16, 3))                                   AS C,
       ( 1 + 1 ) * CAST(1 AS NUMERIC(16, 2)) * CAST(1 AS INT)          AS D,--NUMERIC(38,2)
       CAST(1.555 AS NUMERIC(16, 3))                                   AS E,
       ( 2 ) * CAST(1 AS NUMERIC(16, 2)) * CAST(1 AS INT)              AS F --NUMERIC(29,2)
INTO   T

数字的最大比例为38

第一个具有NUMERIC(38,0)的else分支,因此也是返回类型。如果else分支评估为99999999999999999999999999999999999999,那么其他任何东西都不会起作用。

第二个具有NUMERIC(38,2)的else分支,因此出于类似的原因,这也是最终的数据类型。为了保持三位数的精确度,需要NUMERIC(38,3),但999999999999999999999999999999999999.99不适合。

第三个有NUMERIC(29,2)的else分支。这不是最大的38比例,因此有一定的空间可以扩大一点并保持规模。最终的返回类型是NUMERIC(30,3)

这当然只是将问题转移到为什么第二个分支的评估方式不同。

在正常的事件过程中,以下表达式都评估为int(检查创建的表的定义)

SELECT ( 1 + 1 ) AS A,
       ( 2 )     AS B
INTO   T2 

因此没有明显的理由说明这两者之间存在不同的行为。但我怀疑通过检查实际值将文字2视为NUMERIC(1,0)

而稍微复杂的1 + 1表达式被视为任何未知整数,并且为NUMERIC(10,0)

然后,您可以在this page中详细说明规则,以便在乘以和除以数字时保持精度和比例。