SQL赋值变量和子查询

时间:2017-07-28 07:14:05

标签: sql sql-server tsql

关于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

SQL Fiddle Here

在执行之前,我认为案例部分应为null = 1 or (0 > 0),并且它将返回0

但是现在,我想知道为什么第二个SQL将返回1

3 个答案:

答案 0 :(得分:6)

只是为了扩展@ Giorgi的答案:

请参阅此执行计划:Optimization concept 由于首先评估@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 Transact-SQL

     

CASE语句按顺序评估其条件,并在满足条件的第一个条件下停止。在某些情况下,在CASE语句接收表达式的结果作为其输入之前,将计算表达式。 评估这些表达式的错误是可能的。