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

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

当然,如果我这样做SELECT @A = NULL了,那么分配就会正确进行。

4

4 回答 4

4

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

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

基本上是selectin 在标量上下文中,如果它没有找到一行,它评估为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

这将为 分配 3 个值@a。分配的最后一个是3,所以这就是查询打印的内容。

于 2012-09-17T07:51:42.003 回答
2

那么选择不返回任何行。所以实际上没有分配。

虽然结果集将有一个空值。

于 2012-09-17T07:51:47.637 回答
2

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

SELECT @A = ...

结果集中只有一行,值定义明确。如果返回行,则可以针对任意行计算一次该值,可以计算多次,直至结果集中的行数。

但是,如果查询产生行,则永远不会执行分配。

于 2012-09-17T07:53:40.473 回答
1
SET @A = (SELECT ValueThatDoesntExist 
                       FROM dbo.MyTable WHERE MyColumn = 'notfound')

这里 NULL 作为执行查询的结果返回

但是当你这样做时

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

查询没有返回任何内容

于 2012-09-17T07:52:25.153 回答