【Oracle】複合トリガー
Oracle11gからの新しい機能。
基本的に行トリガーは自分自身のレコードを更新することはできない。
でも、複合トリガーを使うとそんなことができてしまったりする。
これは便利ではあるが、開発では非機能要件をしっかり考慮しておかないと
運用でかなり危ない状況に陥る可能性があるので、慎重に使わなければならないもの。
とりあえず、簡単なものを作ってみる。
毎度のことだが、テーブルの構成は以下の記事にある。
fubukin.hatenablog.com
サンプルで作ってるテーブルの主キーの設定はここの記事の最後くらいにある。
fubukin.hatenablog.com
そして、事前準備として
シーケンスを作っておく
CREATE SEQUENCE "TEST_SEQ" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 6060 CACHE 20 NOORDER NOCYCLE;
複合トリガーの作成。
トリガーの起動順序は
1.BEFORE行トリガー
2.BEFORE文トリガー
3.AFTER行トリガー
4.AFTER文トリガー
CREATE OR REPLACE TRIGGER TEST_INSERT_COMPOUND FOR INSERT ON TABLE1 /*****************************************************************/ -- 共通の宣言のセクション /*****************************************************************/ COMPOUND TRIGGER /*共通の宣言部(共通の変数などを宣言する)*/ /*テーブル配列定義*/ TYPE TABLE1_TYPE IS TABLE OF TABLE1%ROWTYPE; TABLE1_REC TABLE1_TYPE :=TABLE1_TYPE(); /*****************************************************************/ -- BEFOREの行のセクション /*****************************************************************/ BEFORE EACH ROW IS BEGIN /*配列拡張*/ TABLE1_REC.EXTEND; /*シーケンス番号を自動で入れる*/ :NEW.A1 := TEST_SEQ.NEXTVAL; TABLE1_REC(TABLE1_REC.COUNT).A1 := :NEW.A1; END BEFORE EACH ROW; /*****************************************************************/ -- BEFOREの文のセクション /*****************************************************************/ /* BEFORE STATEMENT IS BEGIN END BEFORE STATEMENT; */ /*****************************************************************/ -- AFTERの行のセクション /*****************************************************************/ /* AFTER EACH ROW IS BEGIN END AFTER EACH ROW; */ /*****************************************************************/ -- AFTERの文のセクション /*****************************************************************/ AFTER STATEMENT IS BEGIN /*値の更新*/ FOR I IN 1..TABLE1_REC.COUNT LOOP UPDATE TABLE1 SET A2 = TO_CHAR(I) ,A3 = TO_CHAR(SYSDATE,'YYYYMMDD') ,A4 = TO_CHAR(SYSDATE,'HH24MISS') ,A5 = ' ' ,A6 = ' ' ,A7 = ' ' ,A8 = ' ' ,A9 = ' ' ,A10 = ' ' ,A11 = ' ' ,A12 = ' ' WHERE A1 = TABLE1_REC(I).A1; END LOOP; TABLE1_REC.DELETE; END AFTER STATEMENT; /*****************************************************************/ -- 終わりのEND; /*****************************************************************/ END TEST_INSERT_COMPOUND;
何も入れない全てNULLになるINSERT文を実行
そして結果を見ると、対象に値が入っている。
非機能要件制約さえ決めておけば、この使い道は結構あると思うんだけどな。