SQL赋值变量和子查询

Pri*_*ner 13 sql t-sql sql-server

我有一个关于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
Run Code Online (Sandbox Code Playgroud)

SQL小提琴在这里

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

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

Paw*_*Dyl 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不保证表达式的计算顺序.请注意,只有在分配中有引用时才会显示效果.

这一切都与内部优化有关.


Gio*_*uri 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,则也可以计算第一个表达式.这意味着如果表中的行与propertytype不同于'INT',并且在那些行中propertyval不可转换为INT,则查询可能由于转换错误而失败.