ORACLE/ADMIN

Compound Triggers

argoLee 2018. 1. 23. 11:27

Compound Triggers



  • 하나의 트리거에 여러 개의 트리거링 타이밍을 기술 한 것으로 COMPOUND TRIGGER구를 기술하면 된다.

  • 개별 트리거링 타이밍에서 밖에서 선언한 전역 변수에 대해 참조가 가능하므로 행 레벨 트리거에서 변하는 값들을 전역 변수(주로 배열처럼 쓰이는 테이블 타입의 컬렉션 변수)에 저장한 후 명령문 레벨 트리거의 AFTER 타이밍에서 한번에 처리함으로써 Trigger Mutating Error(ORA-04091을 예방 할 수 있다.)

     

    [형식]


 
CREATE OR REPLACE TRIGGER 트리거이름
  FOR 트리거링 이벤트 ON 테이블명
    COMPOUND TRIGGER
  -- 전역 변수 선언
  g_global_variable VARCHAR2(10);
 
  BEFORE STATEMENT IS   --명령문 레벨 트리거 BEFORE
  BEGIN
    NULL; -- Do something here.
  END BEFORE STATEMENT;
 
  BEFORE EACH ROW IS  --행레벨 트리거 BEFORE
  BEGIN
    NULL; -- Do something here.
  END BEFORE EACH ROW;
 
  AFTER EACH ROW IS  --행레벨 트리거 AFTER
  BEGIN
    NULL; -- Do something here.
  END AFTER EACH ROW;
 
  AFTER STATEMENT IS   --명령문 레벨 트리거 AFTER
  BEGIN
    NULL; -- Do something here.
  END AFTER STATEMENT;
 
END <trigger-name>;
/
 


 


-- 앞 예제에서 작성한 Mutating Table Exception Compound Trigger를 이용하여 해결해 보자.

SQL> drop trigger tr_test2_trigger;

 

트리거가 삭제되었습니다.

 

SQL> drop trigger tr_test2_trigger2;

 

트리거가 삭제되었습니다.

 

SQL> CREATE OR REPLACE TRIGGER tr_test2_compound_trigger

  2    FOR INSERT OR UPDATE ON tr_test2

  3      COMPOUND TRIGGER

  4    TYPE type_change_tab IS TABLE OF tr_test2_log%ROWTYPE;

  5    g_change_tab  type_change_tab := type_change_tab();

  6

  7    AFTER EACH ROW IS

  8    BEGIN

  9      g_change_tab.extend;

 10      g_change_tab(g_change_tab.last).id           := tr_test2_log_seq.NEXTVAL;

 11      IF INSERTING THEN

 12        g_change_tab(g_change_tab.last).action     := 'INSERT';

 13      ELSE

 14        g_change_tab(g_change_tab.last).action     := 'UPDATE';

 15      END IF;

 16      g_change_tab(g_change_tab.last).tr_test2_id      := :new.id;

 17      g_change_tab(g_change_tab.last).cr_date := SYSTIMESTAMP;

 18    END AFTER EACH ROW;

 19

 20    AFTER STATEMENT IS

 21    BEGIN

 22      FOR i IN g_change_tab.first .. g_change_tab.last LOOP

 23        SELECT COUNT(*)

 24        INTO   g_change_tab(i).count

 25        FROM   tr_test2;

 26      END LOOP;

 27

 28      FORALL i IN g_change_tab.first .. g_change_tab.last

 29        INSERT INTO tr_test2_log VALUES g_change_tab(i);

 30

 31      g_change_tab.delete;

 32    END AFTER STATEMENT;

 33

 34  END tr_test2_compound_trigger;

 35  /

 

트리거가 생성되었습니다.

 

SQL> INSERT INTO tr_test2 (id, name) VALUES (tr_test2_seq.NEXTVAL, 'OJC');

 

개의 행이 만들어졌습니다.