このクエリが機能するのはなぜですか?


37

Oracle 12cでは、table_a(id、name)とtable_b(id)の2つのテーブルがあります。

このクエリが例外を返さないのはなぜですか?

select * from table_a where name in (select name from table_b);

私が理解していることから、Oracleはこれを

select * from table_a where name = name;

しかし、私が得られないのはなぜですか?

回答:


61

クエリはtable_bname列がなくても構文的に正しい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_b1行以上ある場合、クエリは次のように実行されます。

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文で回避インナーキャプチャ段落:

ステートメント内の各列参照を適切なテーブルエイリアスで修飾します。


SQLエンジンの内部動作をどのように正確に分析しましたか?
RinkyPinku

8

なぜなら

ネストされたサブクエリが、サブクエリの1レベル上の親ステートメントを参照するテーブルの列を参照する場合、Oracleは相関サブクエリを実行します。 http://docs.oracle.com/cd/E11882_01/server.112/e41084/queries007.htm#SQLRF52357

これは、サブクエリが相関しているかどうかを判断するために、Oracle 外部ステートメントコンテキストも含めてサブクエリの名前を解決しようとする必要があることを意味します。接頭辞なしのname場合、可能な唯一の解決策です。


4

にはnameフィールドがないtable_bため、Oracleはからフィールドを取得しますtable_a。私は試してみましたEXPLAIN PLANが、これは私に唯一のものがあることを与えましたTABLE ACCESS FULL。これにより、両方のテーブルの間にある種のデカルト積が生成され、その結果、すべての名前のリストtable_aがサブクエリによって返されます。


5
「table_bには名前フィールドがないため、Oracleはtable_aから名前フィールドを取得します。」正しい。「これにより、ある種のデカルト積が生成されると思われます。」違う。クエリにはがありfrom table_a where ...ます。null table_a以外のすべての行を返しnameます。
ypercubeᵀᴹ

1
TABLE ACCESS FULLこれは、シーケンシャルスキャンを実行していることをOracleが伝える方法にすぎません。
ジョイシボディオ

1
あなたのPLANは無関係です-巨大なテーブルでインデックスを作成しているかもしれません-テストデータで実行していると思いますか?
ベレース
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.