INSTEAD OF SQL トリガー

INSTEAD OF トリガーとは、SQL UPDATE ステートメント、DELETE ステートメントまたは INSERT ステートメントの「代わりに」処理される SQL トリガーです。 SQL 前トリガーや後トリガーとは異なり、INSTEAD OF トリガーを定義できるのはビューのみで、表では定義できません。

INSTEAD OF トリガーは、本質的には挿入、更新、削除ができないビューで、挿入、更新、削除を可能にします。 削除可能、更新可能、挿入可能の各ビューについての詳細は、CREATE VIEW を参照してください。

つまり、SQL INSTEAD OF トリガーをビューに追加すると、それまでは読み取りしかできなかったビューが、挿入、更新、または削除操作のターゲットとして使用できるようになります。 INSTEAD OF トリガーはビューを保守するために必要な操作を定義します。

表へのアクセスを制御するためにビューを使用できるようになります。 INSTEAD OF トリガーは、表へのアクセス制御の保守を単純化します。

INSTEAD OF トリガーの使用

以下に示すビュー V1 の定義は、更新、削除、挿入が可能です。
CREATE TABLE T1 (C1 VARCHAR(10), C2 INT)
CREATE VIEW V1(X1) AS SELECT C1 FROM T1 WHERE C2 > 10
以下の挿入ステートメントの場合、表 T1 の C1 が値 'A' に割り当てられます。C2 には NULL 値が割り当てられます。NULL 値が原因で、ビュー V1 の C2 > 10 という選択基準に新規行が一致しない可能性があります。
INSERT INTO V1 VALUES('A')
INSTEAD OF トリガー IOT1 を追加することにより、ビューで選択される行に異なる値を指定できるようになります。
CREATE TRIGGER IOT1 INSTEAD OF INSERT ON V1
REFERENCING NEW AS NEW_ROW
FOR EACH ROW MODE DB2SQL
INSERT INTO T1 VALUES(NEW_ROW.X1, 15)

ビューを削除可能にする

以下の結合ビュー V3 の定義は、更新、削除、挿入ができません。
CREATE TABLE A (A1 VARCHAR(10), A2 INT)
CREATE VIEW V1(X1) AS SELECT A1 FROM A

CREATE TABLE B (B1 VARCHAR(10), B2 INT)
CREATE VIEW V2(Y1) AS SELECT  B1 FROM B

CREATE VIEW V3(Z1, Z2) AS SELECT V1.X1, V2.Y1 FROM V1, V2 WHERE V1.X1 = 'A' AND V2.Y1 > 'B'
INSTEAD OF トリガー IOT2 を追加するには、ビュー V3 を削除できるようにします。
CREATE TRIGGER IOT2 INSTEAD OF DELETE ON V3
REFERENCING OLD AS OLD_ROW
FOR EACH ROW MODE DB2SQL
BEGIN
  DELETE FROM A WHERE A1 = OLD_ROW.Z1;
  DELETE FROM B WHERE B1 = OLD_ROW.Z2;
END
このトリガーを使用することで、以下の DELETE ステートメントが許可されます。 このトリガーにより、「A」の値 A1 を持つ表 A からすべての行と、「X」の値 B1 を持つ表 B からすべての行が削除されます。
DELETE FROM V3 WHERE Z1 = 'A' AND Z2 = 'X'

複数の視点で定義された視点を持つ INSTEAD OF トリガー

以下に示す、V1 に定義されたビュー V2 の定義は本質的に挿入、更新、削除ができません。
CREATE TABLE T1 (C1 VARCHAR(10), C2 INT)
CREATE TABLE T2 (D1 VARCHAR(10), D2 INT)
CREATE VIEW V1(X1, X2) AS SELECT C1, C2 FROM T1
UNION SELECT D1, D2 FROM T2

CREATE VIEW V2(Y1, Y2) AS SELECT X1, X2 FROM V1
V1 に INSTEAD OF トリガー IOT1 を追加しても、V2 は更新可能になりません。
CREATE TRIGGER IOT1 INSTEAD OF UPDATE ON V1
REFERENCING OLD AS OLD_ROW NEW AS NEW_ROW
FOR EACH ROW MODE DB2SQL
BEGIN
  UPDATE T1 SET C1 = NEW_ROW.X1, C2 = NEW_ROW.X2 WHERE
    C1 = OLD_ROW.X1 AND C2 = OLD_ROW.X2;
  UPDATE T2 SET D1 = NEW_ROW.X1, D2 = NEW_ROW.D2 WHERE
    D1 = OLD_ROW.X1 AND D2 = OLD_ROW.X2;
END

ビュー V2 の元の定義が更新不可のままになるため、ビュー V2 も更新不可のままになります。

前トリガーおよび AFTER のトリガー INSTEAD OF との使用

INSTEAD OF トリガーをビューに追加しても、基礎となる表に定義された BEFORE および後トリガーが競合することはありません。
CREATE TABLE T1 (C1 VARCHAR(10), C2 DATE)
CREATE TABLE T2 (D1 VARCHAR(10))

CREATE TRIGGER AFTER1 AFTER DELETE ON T1
REFERENCING OLD AS OLD_ROW
FOR EACH ROW MODE DB2SQL
  DELETE FROM T2 WHERE D1 = OLD_ROW.C1

CREATE VIEW V1(X1, X2) AS SELECT SUBSTR(T1.C1, 1, 1), DAYOFWEEK_ISO(T1.C2) FROM T1

CREATE TRIGGER IOT1 INSTEAD OF DELETE ON V1
REFERENCING OLD AS OLD_ROW
FOR EACH ROW MODE DB2SQL
  DELETE FROM T1 WHERE C1 LIKE (OLD_ROW.X1 CONCAT '%')

ビュー V1 に対する削除処理を行うことで、結果的に AFTER DELETE トリガーである AFTER1 が活動化されます。これは、 トリガー IOT1 が表 T1 上で削除を実行するためでもあります。つまり、表 T1 の削除が結果的に AFTER1 トリガーを活動化します。

依存関係にある視点と INSTEAD OF トリガー

ビューに INSTEAD OF トリガーを追加するときに、 ビューの定義が複数のビューを参照し、その中に INSTEAD OF トリガーを定義したビューが含まれる場合は、UPDATE、DELETE、および INSERT の 3 種類すべての操作について、INSTEAD OF トリガーを定義します。その際、定義されたビューの機能と、その他の依存関係にあるビューがもつ機能とが混乱しないようにします。