transact sql如何知道我在这个子查询中引用了哪个表?

时间:2014-01-29 00:24:44

标签: sql sql-server

这是关于t-sql如何决定哪个“列”在子查询范围内的文档的问题。我试过google-ing出现this link,但它没有解释。

这是一个可运行的例子。 update语句将#a.a中的唯一条目设置为null。可能这是因为对别名a的子查询引用解析为表#b,其中没有与值1匹配的行,因此将null返回到外部update查询。

if object_id('tempdb..#a') is not null
drop table #a

if object_id('tempdb..#b') is not null
drop table #b

create table #a (a int)
create table #b (a int)

insert into #a values (1)
insert into #b values (2)

update a
set a = (select a from #b as a where a.a = 1)
from #a as a

是否有说明此设计选择的文档?这是不明确的,因为如果我更改update语句以使用其他别名,#a.a中的最终值为2

update aa
set a = (select a from #b as a where aa.a = 1)
from #a as aa

2 个答案:

答案 0 :(得分:1)

This引用可能会更好地解释它。

这个想法非常简单。表别名被解释为“第一个”表定义,从子查询的当前级别开始,然后向外移动。子查询中的表别名不能在外部查询中使用,因此引用只能“向内”移动。

在你的例子中:

update a
set a = (select a from #b as a where a.a = 1)
from #a as a

a.a指的是表a的列a。在子查询中,表a定义为#b。这是参考。

在此查询中:

update aa
set a = (select a from #b as a where aa.a = 1)
from #a as aa;

表别名为aa。这未在子查询中定义。它在下一级定义,因此它引用#a

通常,不要在查询中为不同的表提供相同的别名(子查询上的别名除外,它们本质上只是特定表的筛选/选定版本)。这可能只会导致混乱。

答案 1 :(得分:1)

在第一个示例中,外部查询和内部查询之间没有关系,因此您要将列“a”的值设置为表#a中每行的内部查询的结果。内部查询返回null,因为#b中没有值为1的行,因此#a中的列a设置为null

在第二个示例中,您仍未提供内部和外部查询之间的关系。所有内部查询都在选择#b中的每个值,因为对于#b中的每一行,#aa的值都是1.您也可以(从#b中选择一个)作为内部查询。

#aa设置为2的原因是#b表中只有1行,其值为2.如果#b中有多行,那么我认为#aa会设置为表#b中最后返回的行的值。因此,如果#b中有2行,第一行的值为2,第二行的值为3,那么我希望#a设置为3.(或者它不会执行)。

无论哪种方式,这些都不是SQL恕我直言的非常好的部分。