様々な基本になるサンプルを記録しています。

不定期更新です。

記事のサイドに使用している商品の紹介も掲載しているので、良ければご覧ください。

【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文を実行
f:id:karinto441:20181015001017p:plain


そして結果を見ると、対象に値が入っている。
f:id:karinto441:20181015001132p:plain


非機能要件制約さえ決めておけば、この使い道は結構あると思うんだけどな。