关于2 SQL,我有一个问题:
declare @i1 bit, @b1 bit
declare @i2 bit, @b2 bit
declare @t table (Seq int)
insert into @t values (1)
-- verify data
select case when (select count(1) from @t n2 where 1 = 2) > 0 then 1 else 0 end
-- result 0
select @i1 = 1, @b1 = case when @i1 = 1 or ((select count(1) from @t n2 where 1 = 2) > 0) then 1 else 0 end from @t n where n.Seq = 1
select @i1, @b1
-- result 1, 0
select @i2 = 1, @b2 = case when @i2 = 1 or (0 > 0) then 1 else 0 end from @t n where n.Seq = 1
select @i2, @b2
-- result 1, 1
在执行之前,我认为案例部分应为null = 1 or (0 > 0)
,并且它将返回0
。
但是现在,我想知道为什么第二个SQL将返回1
答案 0 :(得分:6)
只是为了扩展@ Giorgi的答案:
请参阅此执行计划:
由于首先评估@i2
(@ i2 = 1),case when @i2 = 1 or anything
将返回1.
另请参阅此msdn条目:https://msdn.microsoft.com/en-us/library/ms187953.aspx和警告部分
如果单个SELECT语句中有多个赋值子句, SQL Server不保证评估的顺序 表达式。请注意,效果仅在有效时才可见 作业中的参考文献。
这一切都与内部优化有关。
答案 1 :(得分:5)
我会将此作为答案发布,因为它是来自Training Kit (70-461)
的非常大的文字:
WHERE propertytype = 'INT' AND CAST(propertyval AS INT) > 10
有些人认为除非优先规则另有规定,谓词 将从左到右进行评估,并且将进行短路 尽可能发生。换句话说,如果是第一个谓词 propertytype ='INT'的计算结果为false,SQL Server将不会评估 第二谓词CAST(propertyval AS INT)> 10因为结果是 已经知道了。基于这个假设,期望是 查询应该永远不会尝试转换不是的东西 敞篷车。
但事实却不同。 SQL Server有 内部支持短路概念;但是,由于 语言中的一次性概念,并不一定如此 以从左到右的顺序评估表达式。它可以决定, 基于成本相关的原因,从第二个表达开始, 然后如果第二个表达式的计算结果为true,则评估 第一个表达。这意味着如果有行中的 tabletype,其中propertytype与'INT'不同,在这些行中 propertyval不能转换为INT,查询可能因a而失败 转换错误。
答案 2 :(得分:4)
只是为了扩展两个答案。
来自Dirty Secrets of the CASE Expression:
CASE不会总是短路
官方文档暗示整个表达式将短路,这意味着它将从左到右评估表达式,并在匹配时停止评估:
The CASE statement evaluates its conditions sequentially and stops with the first condition whose condition is satisfied.
和MS Connect:
CASE语句按顺序评估其条件,并在满足条件的第一个条件下停止。在某些情况下,在CASE语句接收表达式的结果作为其输入之前,将计算表达式。 评估这些表达式的错误是可能的。