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 = ...

関連項目:

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;
/