SELECT文およびDML文の内部取得の回避
次の推奨事項を遵守することによって、SELECT文、SELECT INTO
文およびDML文における参照の内部取得を防止できます。
-
文内の各表に対して一意の別名を指定します。
-
文で参照される項目を所有しているスキーマと同じ名前を表の別名に指定しないようにします。
-
文内の列の各参照を適切な表の別名で修飾します。
例B-7では、スキーマhr
が表tab1
およびtab2
を所有しています。表tab1
にはtab2
という名前の列があり、その抽象データ型(ADT)は属性a
を持っています。表tab2
にはa
という名前の列はありません。推奨事項に反して、この問合せでは、表tab1
に別名hr
を指定して表tab2
を参照しています。そのため、この問合せ内の参照hr.tab2.a
は、表tab1
、列tab2
、属性a
に解決されます。その後、この例では、列a
を表tab2
に追加しています。今度は、問合せ内の参照hr.tab2.a
は、スキーマhr
、表tab2
、列a
に解決されます。表tab2
の列a
は、表tab1
の列tab2
の属性a
への参照を取得します。
ここでのトピック
例B-7 属性の参照の内部取得
CREATE OR REPLACE TYPE type1 AS OBJECT (a NUMBER); / DROP TABLE tab1; CREATE TABLE tab1 (tab2 type1); INSERT INTO tab1 (tab2) VALUES (type1(10)); DROP TABLE tab2; CREATE TABLE tab2 (x NUMBER); INSERT INTO tab2 (x) VALUES (10); /* Alias tab1 with same name as schema name, a bad practice used here for illustration purpose. Note lack of alias in second SELECT statement. */ SELECT * FROM tab1 hr WHERE EXISTS (SELECT * FROM hr.tab2 WHERE x = hr.tab2.a);
結果:
TAB2(A) --------------- TYPE1(10) 1 row selected.
表tab2
(スキーマhr
に属する)への列a
の追加:
ALTER TABLE tab2 ADD (a NUMBER);
ここでこの問合せを実行すると、hr.tab2.a
は、スキーマhr
、表tab2
、列a
に解決されます。この内部取得を回避するために、問合せに推奨事項を適用します。
SELECT * FROM hr.tab1 p1 WHERE EXISTS (SELECT * FROM hr.tab2 p2 WHERE p2.x = p1.tab2.a);
属性およびメソッドへの参照の修飾
表の要素の属性やメソッドを参照するには、表に別名を付け、その別名を使用して、属性やメソッドに対する参照を修飾します。
例B-8の表tbl1
には、属性x
を持つADTであるデータ型t1
の列col1
があります。この例は、tbl1.col1.x
への適切な参照と適切でない参照をいくつか示しています。
例B-8 ADT属性の参照の修飾
CREATE OR REPLACE TYPE t1 AS OBJECT (x NUMBER); / DROP TABLE tb1; CREATE TABLE tb1 (col1 t1);
次のINSERT
文の参照では、列リストがないため、別名は不要です。
BEGIN INSERT INTO tb1 VALUES ( t1(10) ); INSERT INTO tb1 VALUES ( t1(20) ); INSERT INTO tb1 VALUES ( t1(30) ); END; /
属性x
への次の参照では、エラーORA-00904が発生します。
UPDATE tb1 SET col1.x = 10 WHERE col1.x = 20; UPDATE tb1 SET tb1.col1.x = 10 WHERE tb1.col1.x = 20; UPDATE hr.tb1 SET hr.tb1.col1.x = 10 WHERE hr.tb1.col1.x = 20; DELETE FROM tb1 WHERE tb1.col1.x = 10;
属性x
への表の別名を使用した次の参照は、適切です。
UPDATE hr.tb1 t SET t.col1.x = 10 WHERE t.col1.x = 20; DECLARE y NUMBER; BEGIN SELECT t.col1.x INTO y FROM tb1 t WHERE t.col1.x = 30; END; / DELETE FROM tb1 t WHERE t.col1.x = 10;
行の式への参照の修飾
行の式は、表の別名への参照として解決する必要があります。行の式は、UPDATE
文のSET
句で使用したり、SQLファンクションREF
またはVALUE
のパラメータにすることができます。
例B-9の表ot1
は、属性x
を持つADTであるデータ型t1
の要素のスタンドアロンのネストした表です。この例は、行の式への適切な参照と適切でない参照をいくつか示しています。
例B-9 行の式への参照の修飾
CREATE OR REPLACE TYPE t1 AS OBJECT (x number); / DROP TABLE ot1; CREATE TABLE ot1 OF t1; BEGIN INSERT INTO ot1 VALUES (t1(10)); INSERT INTO ot1 VALUES (20); INSERT INTO ot1 VALUES (30); END; /
次の参照では、エラーORA-00904が発生します。
UPDATE ot1 SET VALUE(ot1.x) = t1(20) WHERE VALUE(ot1.x) = t1(10); DELETE FROM ot1 WHERE VALUE(ot1) = (t1(10));
表の別名を使用した次の参照は、適切です。
UPDATE ot1 o SET o = (t1(20)) WHERE o.x = 10; DECLARE n_ref REF t1; BEGIN SELECT REF(o) INTO n_ref FROM ot1 o WHERE VALUE(o) = t1(30); END; / DECLARE n t1; BEGIN SELECT VALUE(o) INTO n FROM ot1 o WHERE VALUE(o) = t1(30); END; / DECLARE n NUMBER; BEGIN SELECT o.x INTO n FROM ot1 o WHERE o.x = 30; END; / DELETE FROM ot1 o WHERE VALUE(o) = (t1(20));