为什么我可以使用子查询中不同表的列?

时间:2017-05-24 15:13:42

标签: sql oracle

在这个例子中,我觉得我不应该犯这个错误:

create table A (A_ID int);
create table B (B_ID int, OTHER_ID int);

insert into A values (123);
insert into B values (456, 123);

select * from A where A_ID in (select A_ID from B);

正确的查询是:

select * from A where A_ID in (select OTHER_ID from B);

由于表B中不存在A_ID,为什么查询不会抛出错误,或者至少失败?

编辑:感谢您的回复!但是,要明确的是,我的问题不是“正确的方法是什么?”#34;我只是好奇为什么会这样做。

4 个答案:

答案 0 :(得分:5)

在具有多个列的写入查询时,应始终包含限定的表名。您的第一个查询被解释为:

select a.*
from A a
where a.A_ID in (select a.A_ID from B b);

这称为相关子查询。它们在任何地方都被允许,除了FROM子句。

您应该将查询编写为:

select a.*
from A a
where a.A_ID in (select b.OTHER_ID from B b);

这可以防止任何错误。如果您最初对列名称进行了限定,那么您的查询将(可能)生成错误:

select a.*
from A a
where a.A_ID in (select b.A_ID from B b);

答案 1 :(得分:3)

您正在讨论的子查询称为相关子查询:这些是在主查询的上下文中运行的查询,因此这些查询提供对作为主查询一部分的任何字段的访问权限

认为不允许对主查询字段的这种使用没有多大意义,否则SQL会失去很多权力。

您可以在Oracle Help Center

中找到更多信息

答案 2 :(得分:3)

它的作用是因为范围

外部查询的所有列都在子查询的范围内(可见)。

您无需限定列,例如:{/ 1>}中的A.A_ID

select * from A where A_ID in (select A.A_ID from B)

如果在找到列的最窄范围内没有歧义。例如,如果B有一个列A_ID,则不需要对其进行限定,但如果外部查询中有多个列被调用,则需要对其进行限定以消除引用的歧义。

答案 3 :(得分:2)

对于您的查询,这是它的运作方式。 A_ID就像一个常数一样工作。

select * from dual
 where 123 in (select 123 from dual);

123并不存在于双重中,但由于双行中存在一行,您可以选择您喜欢的任何值。

select * from dual;

输出 -

Dummy
X

根据OP的查询 -

select * from A where A_ID in (select A_ID from B);

如果以上查询

select * from A where A_ID in (select A_ID from B where 1=2);

它不会返回任何记录。

当列名相同时,列名的范围会出现,需要通过表别名

进行限定