关于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
分支的不太精确的结果。
答案 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中详细说明规则,以便在乘以和除以数字时保持精度和比例。