在这个例子中,我觉得我不应该犯这个错误:
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;我只是好奇为什么会这样做。
答案 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);
它不会返回任何记录。
当列名相同时,列名的范围会出现,需要通过表别名
进行限定