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

时间:2012-09-17 07:49:18

标签: sql tsql select

每天我都会学到一些新东西,似乎:)有人可以向我解释以下代码行为背后的基本原理:

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

从我看到的情况来看,如果结果集为NULL,则SET会更改变量的值,而SELECT则不会。这是正常的ANSI行为还是特定于T-SQL?

当然,如果我SELECT @A = NULL,则分配正确。

4 个答案:

答案 0 :(得分: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 :(得分:2)

那么select不会返回任何行。所以实际上没有任务。

虽然该集合的结果为null。

答案 2 :(得分:2)

SELECT子句中的变量赋值是不可预测的。当你有:

SELECT @A = ...

完全一行在结果集中,该值已明确定义。如果返回多个行,则可以为任意行计算值 一次,或者可以计算多次次,直到结果集中的行数。

但是,如果查询生成行,则永远不会执行赋值。

答案 3 :(得分:1)

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

此处由于执行查询

而返回NULL

但是当你做的时候

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

查询没有返回任何内容