回答:
クエリは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)
-は同じ列を1つ持つテーブルです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文で回避インナーキャプチャ段落:
ステートメント内の各列参照を適切なテーブルエイリアスで修飾します。
なぜなら
ネストされたサブクエリが、サブクエリの1レベル上の親ステートメントを参照するテーブルの列を参照する場合、Oracleは相関サブクエリを実行します。 http://docs.oracle.com/cd/E11882_01/server.112/e41084/queries007.htm#SQLRF52357
これは、サブクエリが相関しているかどうかを判断するために、Oracle は外部ステートメントコンテキストも含めてサブクエリの名前を解決しようとする必要があることを意味します。接頭辞なしのname
場合、可能な唯一の解決策です。
にはname
フィールドがないtable_b
ため、Oracleはからフィールドを取得しますtable_a
。私は試してみましたEXPLAIN PLAN
が、これは私に唯一のものがあることを与えましたTABLE ACCESS
FULL
。これにより、両方のテーブルの間にある種のデカルト積が生成され、その結果、すべての名前のリストtable_a
がサブクエリによって返されます。
from table_a where ...
ます。null table_a
以外のすべての行を返しname
ます。
TABLE ACCESS FULL
これは、シーケンシャルスキャンを実行していることをOracleが伝える方法にすぎません。