这是关于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
答案 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恕我直言的非常好的部分。