在处理NULL时,T-SQL中的SELECT @Var和SET @Var的行为表现

5

每天似乎我都能学到新东西 :) 请问有人能解释一下以下代码行为的原理吗:

DECLARE @A INT

SET @A = 15
SET @A = (SELECT ValueThatDoesntExist FROM dbo.MyTable WHERE MyColumn = 'notfound')

SELECT @A
-- Rsultset is NULL

SET @A = 15
SELECT @A = ValueThatDoesntExist FROM dbo.MyTable WHERE MyColumn = 'notfound'

SELECT @A
-- Resultset is 15

据我所见,如果结果集为空,SET会改变变量的值,而SELECT不会。这是正常的ANSI行为还是特定于T-SQL的行为?

当然,如果我执行SELECT @A = NULL,赋值会发生正确。

4个回答

4

第一个版本将A设置为查询结果:

SET @A = (SELECT ValueThatDoesntExist FROM dbo.MyTable WHERE MyColumn = 'notfound')

基本上select在标量环境下运行,如果没有找到行,则返回null

第二个版本为结果集中的每一行设置A:

SELECT @A = ValueThatDoesntExist FROM dbo.MyTable WHERE MyColumn = 'notfound'

由于没有行,A永远不会被赋值。另一个例子:

declare @a int

select  @a = i
from    (
        select  1
        union all select 2
        union all select 3
        ) as SubQueryAlias(i)
order by
        i

select  @a

这将给@a分配3个值。最后一个被分配的是3,因此这就是查询打印的内容。

1
对于你最后的例子 - 我不确定你是否保证@a之后会是3,也不确定是否会执行3个赋值。 - Damien_The_Unbeliever

2

查询返回零行,因此实际上没有任何分配。

而集合将具有空结果。


2

SELECT语句中的变量赋值是相当不可预测的。例如:

SELECT @A = ...

当且仅当结果集中恰好有一行时,该值才被定义。如果返回多行,则该值可以计算一次,对于任意一行,或者它可以被计算多次,直到结果集中的行数为止。

但是,如果查询产生零行,则不会执行赋值操作。


1
SET @A = (SELECT ValueThatDoesntExist 
                       FROM dbo.MyTable WHERE MyColumn = 'notfound')

执行查询后,返回NULL作为结果

但是当您执行以下操作时

SELECT @A = ValueThatDoesntExist FROM dbo.MyTable WHERE MyColumn = 'notfound'

查询没有返回任何结果


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接