2

私は次のようなクエリを持っています

SELECT tran_number
  FROM table_a WHERE customer_id IN
          (SELECT customer_id 
             FROM table_b
            WHERE customer_key = 89564
                  AND (   other_phn_area_code
                       || other_phnum_pfx_num
                       || other_phnum_sfx_num IN
                          (123456789)))
       AND phn_area_code || phnum_pfx_num || phnum_sfx_num IN (123456789)

上記のコードは正常に動作しています。懸念は内部クエリにあります(以下の内部クエリのみをコピーしました)...

(SELECT customer_id 
                 FROM table_b
                WHERE customer_key = 89564
                      AND (   other_phn_area_code
                           || other_phnum_pfx_num
                           || other_phnum_sfx_num IN
                              (123456789)))

このクエリを実行すると、エラーが発生しcustomer_id: invalid identifierます。実際にtable_bは、 という名前のフィールドはありませんcustomer_id。もしそうなら、上記の内部クエリとして使用すると、問題なくどのように機能しますか。

これを理解するのを手伝ってください。

データベースの詳細は以下

Oracle 11G Enterprise edition 11.2.0.2.0
PL/SQL Release 11.2.0.2.0
4

3 に答える 3

7

whereその内部選択の条件に結果がある場合、列customer_idtable_a選択されます。そうでない場合は選択されません。外側の選択は、in条件でそれをチェックします。それは、「内側の選択が true を返す場合にのみ何かを返す」と言っているようなものです。

于 2012-07-17T08:16:21.713 に答える
3

それは範囲の問題です。Oracleは、最も内側のサブクエリから始まり、外側に向かって識別子を検証します。元のクエリにテーブルエイリアスを追加すると、状況がより明確になる可能性があります。

SELECT t1.tran_number 
  FROM table_a t1
  WHERE t1.customer_id IN 
          (SELECT t1.customer_id  
             FROM table_b t2 
            WHERE t2.customer_key = 89564 
                  AND (   t2.other_phn_area_code 
                       || t2.other_phnum_pfx_num 
                       || t2.other_phnum_sfx_num IN 
                          (123456789))) 
       AND t1.phn_area_code || t1.phnum_pfx_num || t1.phnum_sfx_num IN (123456789) 

実際、外部クエリはEXISTSのテストとしてサブクエリを使用しています。つまり、CUSTOMER_KEYの特定の値とそれらの他の列の存在をチェックするだけです。これが希望どおりでない場合は、サブクエリの列名を変更する必要があります。(そして、それはかなり良い賭けです。おそらくメインクエリから不可解な結果が得られているので、サブクエリを個別に調査しているのです)。

これらのシナリオでエイリアスを使用することは、常に良い習慣です。次のようにサブクエリのエイリアスを作成した場合:

....
  WHERE t1.customer_id IN 
          (SELECT t2.customer_id  
             FROM table_b t2 
            WHERE t2.customer_key = 89564 
....

エラーはすぐに明らかになります。


SQLリファレンスでは、サブクエリでのスコープの操作について説明していますが、見つけるのは困難です。それが言うことはこれです:

「Oracleは、サブクエリで指定されたテーブルを調べてから、親ステートメントで指定されたテーブルを調べることにより、サブクエリの非修飾列を解決します。」

スコープのより明確な説明は、PL/SQLのドキュメントにあります。SQLサブクエリも同じように機能します。 詳細をご覧ください

于 2012-07-17T08:20:08.747 に答える
0

これはINの既知のバグです。テーブルエイリアスを使用すると、エラーが発生します

SELECT tran_number 
  FROM table_a WHERE customer_id IN 
          (SELECT b.customer_id  
             FROM table_b b
            WHERE customer_key = 89564 
                  AND (   other_phn_area_code 
                       || other_phnum_pfx_num 
                       || other_phnum_sfx_num IN 
                          (123456789))) 
       AND phn_area_code || phnum_pfx_num || phnum_sfx_num IN (123456789) 

また、EXISTSを使用して、このタイプのサイレント動作を回避します

SELECT tran_number 
  FROM table_a as t1 WHERE EXISTS  
          (SELECT *
             FROM table_b as b
            WHERE customer_key = 89564 
                  AND (   other_phn_area_code 
                       || other_phnum_pfx_num 
                       || other_phnum_sfx_num IN 
                          (123456789))
        AND b.customer_id  =t1.customer_id) 
       AND phn_area_code || phnum_pfx_num || phnum_sfx_num IN (123456789) 
于 2012-07-17T08:18:18.503 に答える