我不明白这种情况下的行为。根据我的理解,使用无效子查询的查询应该会导致错误。但是在这个例子中它返回了一些行。
试验数据:
create table test_values ( tst_id number, tst_id2 number, tst_value varchar2( 10 ) );
create table test_lookup ( tst_id number, tst_value varchar2( 10 ) );
insert into test_values( tst_id, tst_id2, tst_value ) values ( 1, 2, 'a' );
insert into test_values( tst_id, tst_id2, tst_value ) values ( 1, 2, 'b' );
insert into test_values( tst_id, tst_id2, tst_value ) values ( 2, 2,'c' );
insert into test_values( tst_id, tst_id2, tst_value ) values ( 2, 2,'d' );
insert into test_lookup( tst_id, tst_value ) values ( 1, 'findMe' );
commit;
按预期工作:
select * from test_values where tst_id in ( select tst_id from test_lookup where tst_value = 'findMe' );
/*
TST_ID TST_ID2 TST_VALUE
---------- ---------- ----------
1 2 b
1 2 a
*/
select tst_id2 from test_lookup where tst_value = 'findMe';
--ORA-00904: "TST_ID2": invalid identifier
但是下面的查询也是检索行,显然是通过从“test_values”-table获取“test_id2”列而不是从子查询中所述的“test_lookup”-table获取,尽管不使用别名内部和外部。
select * from test_values where tst_id in ( select tst_id2 from test_lookup where tst_value = 'findMe' );
/*
TST_ID TST_ID2 TST_VALUE
---------- ---------- ----------
2 2 c
2 2 d
*/
答案 0 :(得分:7)
原因是因为当子查询中不存在未列别的列但外部查询中确实存在时,Oracle假定您引用外部查询中的列。
使用别名时,您混淆的查询将如下所示:
select *
from test_values tv
where tv.tst_id in (select tv.tst_id2
from test_lookup tl
where tl.tst_value = 'findMe');
希望这会让事情变得更清楚?
您所看到的问题是一个非常好的示例,说明为什么您应该始终使用哪个表标记您的列 - 这样可以更轻松地维护查询以便开始!
答案 1 :(得分:4)
当你的'破解'查询被用作子查询时,它仍然可以引用外部查询的表列;这对于工作的相关性是必要的。它正在从tst_id2
表中获取test_values
列。如果两个表具有相同的列,则内部表优先,但这不是这种情况。
Oracle通过查看子查询中指定的表,然后查找父语句中指定的表,解析子查询中的非限定列。
您可以通过添加表别名来查看正在发生的事情;这仍然是错误:
select * from test_values tv where tst_id in (
select tl.tst_id2 from test_lookup tl where tl.tst_value = 'findMe' );
ORA-00904: "TL"."TST_ID2": invalid identifier
但这有效:
select * from test_values tv where tst_id in (
select tv.tst_id2 from test_lookup tl where tl.tst_value = 'findMe' );
明确使用test_values
列(通过tv
别名);你的原始查询是做同样的,但含蓄地。