取得

宣言または定義が、別の有効範囲における参照の正常な解決の妨げになる場合、その宣言または定義が参照を「取得する」と呼びます。通常、取得は移行またはスキーマのアップグレードの結果として行われます。

ここでのトピック

ノート:

同一有効範囲の取得および内部取得は、SQLスコープでのみ発生します。

外部取得

外部取得が発生するのは、内部有効範囲内の項目に解決されていた内部有効範囲内の名前が、外部有効範囲内の項目に解決される場合です。PL/SQLとSQLは両方とも、外部取得を防止する設計になっているので、外部取得の回避に慎重になる必要はありません。

同一有効範囲の取得

同一有効範囲の取得が発生するのは、結合に使用される2つの表のどちらかに列が追加され、この新しい列の名前が他の表の列名と同じである場合です。その名前の列が1つの表にのみ存在する場合は、名前が未修飾で結合に現れる可能性があります。同一有効範囲の取得を回避するには、その列名が結合に現れるすべての場所で、列名を適切な表名で修飾する必要があります。

内部取得

内部取得が発生するのは、外部有効範囲内の項目に解決されていた内部有効範囲内の名前が、内部有効範囲内の項目に解決される場合か解決できない場合のいずれかです。最初のケースでは結果が変わる可能性があります。2番目のケースではエラーが発生します。

例B-6では、新しい列は、同じ名前の古い列の参照を取得します。col2は、新しい列col2が表tab2に追加される前はtab1.col2に解決され、追加された後はtab2.col2に解決されます。

内部取得を防止するには、「SELECT文およびDML文の内部取得の回避」のルールに従います。

例B-6 列の参照の内部取得

tab1にはcol2という名前の列がありますが、表tab2にはありません。

DROP TABLE tab1;
CREATE TABLE tab1 (col1 NUMBER, col2 NUMBER);
INSERT INTO tab1 (col1, col2) VALUES (100, 10);

DROP TABLE tab2;
CREATE TABLE tab2 (col1 NUMBER);
INSERT INTO tab2 (col1) VALUES (100);

そのため、内側のSELECT文では、col2への参照が列tab1.col2に解決されます。

CREATE OR REPLACE PROCEDURE proc AUTHID DEFINER AS
  CURSOR c1 IS
    SELECT * FROM tab1
    WHERE EXISTS (SELECT * FROM tab2 WHERE col2 = 10);
BEGIN
  OPEN c1;
  CLOSE c1;
END;
/

tab2への列col2の追加:

ALTER TABLE tab2 ADD (col2 NUMBER);

これでプロシージャprocは無効になりました。次に起動する際に、このプロシージャはデータベースによって自動的に再コンパイルされ、内側のSELECT文におけるcol2への参照は、列tab2.col2に解決されます。