Answers:
即使table_b
没有name
列,查询在语法上也是正确的SQL 。原因是范围解析。
解析查询时,首先检查是否table_b
有name
列。既然没有,则table_a
进行检查。仅当两个表都没有name
列时,它才会引发错误。
最后,查询执行为:
select a.*
from table_a a
where a.name in (select a.name
from table_b b
);
至于结果,查询将为table_a
子查询的每一行提供(select name from table_b)
-或(select a.name from table_b b)
-表格,该表格的单列a.name
值相同,行数与相同table_b
。因此,如果table_b
有1行或更多行,则查询运行如下:
select a.*
from table_a a
where a.name in (a.name, a.name, ..., a.name) ;
要么:
select a.*
from table_a a
where a.name = a.name ;
要么:
select a.*
from table_a a
where a.name is not null ;
如果table_b
为空,查询将不返回任何行(thnx指向@ughai指出这种可能性)。
那(您没有得到错误的事实)可能是所有列引用都应以表名/别名作为前缀的最佳原因。如果查询是:
select a.* from table_a where a.name in (select b.name from table_b);
您将立即得到错误。当省略表前缀时,发生此类错误并不困难,尤其是在更复杂的查询中,甚至更重要的是,也不会引起注意。
另请参阅Oracle文档:静态SQL语句中的名称解析,内部捕获中的示例B-6 和SELECT和DML语句中的避免内部捕获段落中的建议:
使用适当的表别名来限定语句中的每个列引用。
因为
当嵌套的子查询引用表中的列时,Oracle会执行相关的子查询,该表引用了子查询上一级的父语句。 http://docs.oracle.com/cd/E11882_01/server.112/e41084/queries007.htm#SQLRF52357
这意味着为了确定子查询是否相关,Oracle也必须尝试在子查询中解析名称,包括外部语句上下文。对于无前缀,name
这是唯一可能的解决方案。
Oracle中没有name
字段,table_b
因此Oracle从中选择一个table_a
。我尝试了,EXPLAIN PLAN
但这只给了我一个TABLE ACCESS
FULL
。我认为这将在两个表之间生成某种笛卡尔积,从而导致table_a
子查询返回所有名称的列表。
from table_a where ...
。它将返回table_a
除name
null 以外的所有行。
TABLE ACCESS FULL
只是Oracle告诉您它正在进行顺序扫描的方式。