6.11 オブジェクト・ビューの操作
オブジェクト表に使用するSQL DMLと同じものを使用して、オブジェクト・ビューのデータを更新、挿入および削除できます。あいまいな表現がなければ、オブジェクト・ビューの実表が更新されます。
ビューは常に直接更新できるわけではありません。
ビューの問合せに結合、集合演算子、集計ファンクション、GROUP BY
またはDISTINCT
句が含まれている場合、ビューの直接更新はできません。ビューの問合せで、ビューの列が疑似列または式に基づいている場合も、ビューの個々の列を直接更新することはできません。
ビューが直接更新できなくても、INSTEAD OF
トリガーを使用して、間接的に更新できます。この操作を行うには、ビューに対して実行するそれぞれのDML文に、INSTEAD
OF
トリガーを定義します。INSTEAD
OF
トリガーには、目的の変更をビューで行うために、ビューの基礎となる表に対して実行する必要のある操作をプログラムします。この後、INSTEAD
OF
トリガーが定義されたDML文を発行すると、関連するトリガーが透過的に実行されます。
注意:
オブジェクト・ビュー階層では、UPDATE
文およびDELETE
文は、SELECT
文と同様に多相性を伴って動作します。つまり、ビューに対して実行されたUPDATE
またはDELETE
文で抽出される行の集合には、指定されたビューのすべてのサブビューにある修飾行も暗黙的に含まれます。
たとえば、Person_v
から全員を削除する次の文により、Student_v
から学生全員が削除され、Employee_v
ビューから従業員全員が削除されます。
DELETE FROM Person_v;
サブビューを除外し、影響する行の対象を、指定されたビューに存在する人たちに限定するには、ONLY
キーワードを使用します。たとえば、次の文は個人のみ更新し、従業員または学生は更新しません。
UPDATE ONLY(Person_v) SET address = ...
関連項目:
-
INSTEAD
OF
トリガーの例は、「変更および妥当性チェックを制御するINSTEAD OFトリガー」を参照してください -
オブジェクト・ビュー階層、および
Student_v
ビューとEmployee_v
ビューを定義する例は、「オブジェクト・ビューの階層」を参照してください。
6.11.1 ビューで更新されるネストした表列
ネストした表を更新するには、新しい要素を挿入したり、既存の要素を更新または削除します。ビューの場合と同様に、仮想または合成のネストした表列は、通常は更新できません。この問題に対処するために、この列の上にINSTEAD
OF
トリガーを作成できます。
(ビューの)ネストした表列に対して定義されたINSTEAD
OF
トリガーは、列を変更するときに起動します。親である行の更新によってコレクション全体が置換される場合は、ネストした表列のINSTEAD
OF
トリガーは起動されないため注意してください。
6.11.2 変更および妥当性チェックを制御するINSTEAD OFトリガー
INSTEAD
OF
トリガーを使用して複合ビューを更新できます。
INSTEAD
OF
トリガーを使用することで、他の方法では更新できない複雑なビューを更新できます。また制約の施行、権限のチェック、DML文の妥当性チェックにも、このトリガーを使用できます。これらのトリガーを使用すると、オブジェクト・ビューを介して作成されたオブジェクトに挿入、更新および削除が行われた結果としての変更を制御できます。
たとえば、ある部門の従業員の数を10以下とするという条件を施行する場合は、従業員ビュー用のINSTEAD
OF
トリガーを作成できます。ビューは更新できるため、DML文の実行にトリガーは必要ありませんが、制約を施行するにはトリガーが必要です。
例6-8に、SQL文を使用してトリガーを実装する方法を示します。
例6-8 ビューのINSTEAD OFトリガーの作成
-- Requires Ex. 6-2, Ex. 6-4, and Ex. 6-6 CREATE TRIGGER emp_instr INSTEAD OF INSERT on emp_view FOR EACH ROW DECLARE dept_var dept_t; emp_count integer; BEGIN -- Enforce the constraint -- First get the department number from the reference UTL_REF.SELECT_OBJECT(:NEW.deptref, dept_var); SELECT COUNT(*) INTO emp_count FROM emp WHERE deptno = dept_var.deptno; IF emp_count < 9 THEN -- Do the insert INSERT INTO emp (empno, empname, salary, deptno) VALUES (:NEW.empno, :NEW.ename, :NEW.salary, dept_var.deptno); END IF; END; /
関連項目: