Oracle 트리거 완벽 가이드: 정의, 문법, 활용 사례

트리거(Trigger)란?

데이터베이스 트리거는 특정 테이블에서 INSERT, UPDATE, DELETE와 같은 DML(데이터 조작어) 이벤트가 발생할 때 자동으로 실행되는 저장 프로시저의 일종입니다. 일반 프로시저와 달리 사용자가 직접 호출하지 않고, 정의된 이벤트가 발생하면 시스템이 자동으로 실행합니다. 주로 데이터 무결성 유지, 비즈니스 규칙 강제, 감사 로그 기록 등에 사용됩니다.

트리거의 4가지 핵심 구성 요소

  1. 트리거 이벤트: 트리거를 활성화하는 SQL 작업(INSERT, UPDATE, DELETE)
  2. 트리거 타이밍: 이벤트 발생 전(BEFORE) 또는 후(AFTER) 실행 여부
  3. 트리거 본문: 실제 실행할 PL/SQL 또는 SQL 로직
  4. 트리거 레벨: 문장 레벨(statement-level) 또는 행 레벨(row-level) 실행 방식

기본 문법

CREATE [OR REPLACE] TRIGGER 트리거명
{BEFORE | AFTER}
{INSERT | UPDATE | DELETE}
ON 테이블명
[FOR EACH ROW]
[WHEN 조건]
BEGIN
   -- 실행할 SQL 로직
END;

실전 예제: 기본 트리거

CREATE OR REPLACE TRIGGER EMP_TRIGGER
AFTER INSERT OR UPDATE
ON EMPLOYEES
FOR EACH ROW
BEGIN
   -- 감사 로그 남기기
   INSERT INTO AUDIT_LOG(TABLE_NAME, ACTION, OLD_VALUE, NEW_VALUE, CHANGE_DATE)
   VALUES('EMPLOYEES', 
          CASE WHEN :OLD.EMPLOYEE_ID IS NULL THEN 'INSERT' ELSE 'UPDATE' END,
          :OLD.SALARY,
          :NEW.SALARY,
          SYSDATE);
END;

DDL vs DML과 트리거의 관계

  • DDL(데이터 정의어): CREATE, ALTER, DROP, TRUNCATE 등. 트리거를 트리거하지 않으며 자동 커밋됨.
  • DML(데이터 조작어): INSERT, UPDATE, DELETE, SELECT 등. 트리거를 트리거할 수 있음.

트리거와 트랜잭션

트리거와 이를 트리거한 DML은 동일한 트랜잭션 내에서 실행됩니다. DML이 커밋되면 트리거의 작업도 커밋되고, 롤백되면 함께 롤백됩니다. 기본적으로 Oracle 트리거 내에서는 DDL 문(CREATE/ALTER/DROP)과 COMMIT/ROLLBACK을 직접 사용할 수 없습니다.

자율 트랜잭션(Autonomous Transaction)을 통한 해결

트리거 내에서 DDL을 실행하거나 별도로 커밋해야 하는 경우 PRAGMA AUTONOMOUS_TRANSACTION을 사용합니다.

CREATE OR REPLACE TRIGGER LOG_TRIGGER
AFTER INSERT ON ORDERS
FOR EACH ROW
DECLARE
   PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
   INSERT INTO LOG_TABLE(ORDER_ID, ACTION_TIME)
   VALUES(:NEW.ORDER_ID, SYSDATE);
   COMMIT;
END;

Oracle 트리거 분류

문장 레벨 트리거 (Statement-level Trigger)

  • DML 문장이 실행될 때 한 번만 실행
  • FOR EACH ROW 절이 없음
  • :NEW:OLD 참조 불가
  • 예: 500행을 INSERT해도 한 번만 실행

행 레벨 트리거 (Row-level Trigger)

  • 영향받는 각 행마다 실행
  • FOR EACH ROW 절 포함
  • :NEW:OLD 참조 가능
  • WHEN 조건으로 필터링 가능
  • 예: 500행 INSERT 시 500번 실행

:NEW 와 :OLD 의사 레코드

작업:NEW:OLD
INSERT새로 삽입된 행NULL
UPDATE변경 후 새 값변경 전 원래 값
DELETENULL삭제된 행

다중 트리거 실행 순서

BEFORE 문장 레벨 → BEFORE 행 레벨 → AFTER 행 레벨 → AFTER 문장 레벨

실무 활용 사례

사례 1: 테이블 A의 변경사항을 테이블 B에 복제

CREATE OR REPLACE TRIGGER SYNC_TRIGGER
AFTER INSERT OR UPDATE ON TABLE_A
FOR EACH ROW
BEGIN
   INSERT INTO TABLE_B(ID, NAME, STATUS, UPDATED_AT)
   VALUES(:NEW.ID, :NEW.NAME, :NEW.STATUS, SYSDATE);
END;

사례 2: 자기 테이블의 특정 컬럼 자동 갱신

CREATE OR REPLACE TRIGGER AUTO_UPDATE_TRIGGER
BEFORE INSERT OR UPDATE ON EMPLOYEES
FOR EACH ROW
BEGIN
   :NEW.LAST_MODIFIED_BY := USER;
   :NEW.LAST_MODIFIED_DATE := SYSDATE;
END;

사례 3: ORA-04091 오류 회피 (변경 중인 테이블 읽기)

테이블 A의 트리거에서 자체 테이블을 읽어야 할 경우, 중간 테이블을 활용한 2단계 접근법 사용:

  1. A 테이블의 AFTER UPDATE 트리거에서 필요한 데이터를 임시 테이블 B에 저장
  2. B 테이블의 AFTER INSERT 트리거(자율 트랜잭션)에서 A 테이블을 읽어 처리

주의사항

  • 트리거 내에서 자기 테이블에 INSERT/UPDATE/DELETE 실행 시 무한 재귀 주의
  • 과도한 트리거 사용은 성능 저하를 유발할 수 있음 (특히 행 레벨 트리거)
  • 가능한 제약 조건(CONSTRAINT)으로 해결할 수 있는 문제는 제약 조건 사용 권장

태그: Oracle PL/SQL Database Trigger Autonomous Transaction

7월 6일 20:43에 게시됨