본문 바로가기
✨ DBMS/etc

[DB] 트리거(Trigger)

by 환풍 2024. 10. 9.
728x90
반응형

트리거(Trigger)란?

**트리거(Trigger)**는 데이터베이스에서 특정 이벤트(예: INSERT, UPDATE, DELETE)가 발생할 때 자동으로 실행되는 저장 프로시저입니다. 트리거는 데이터 무결성, 비즈니스 규칙 적용, 로깅 및 감사 용도로 주로 사용됩니다.

트리거의 특징:

  1. 자동 실행: 사용자가 명시적으로 호출하지 않아도 특정 이벤트가 발생하면 자동으로 실행됩니다.
  2. 데이터 무결성 보장: 데이터 입력, 수정, 삭제 시 조건을 검증하거나 자동으로 관련 데이터를 처리함으로써 데이터 무결성을 유지할 수 있습니다.
  3. 테이블에 바인딩됨: 트리거는 특정 테이블에 바인딩되며, 해당 테이블에서 지정된 이벤트가 발생할 때만 실행됩니다.
  4. 트랜잭션 내에서 실행: 트리거는 트랜잭션의 일부로 실행되므로 트랜잭션이 롤백되면 트리거의 결과도 롤백됩니다.

트리거의 주요 구성 요소

  1. 이벤트(Event): 트리거를 실행시키는 데이터베이스의 특정 작업을 말합니다. 일반적으로 다음 세 가지가 있습니다.
    • INSERT: 새로운 레코드가 테이블에 삽입될 때 실행.
    • UPDATE: 기존 레코드가 수정될 때 실행.
    • DELETE: 기존 레코드가 삭제될 때 실행.
  2. 타이밍(Timing): 트리거가 이벤트 전에 실행될지, 후에 실행될지 설정할 수 있습니다.
    • BEFORE: 트리거가 이벤트 전에 실행됩니다. 예를 들어, 데이터가 삽입되기 전에 실행되는 로직을 정의할 수 있습니다.
    • AFTER: 트리거가 이벤트가 발생한 후에 실행됩니다. 예를 들어, 데이터가 삽입된 후 특정 작업을 수행할 수 있습니다.
  3. 작업(Statement): 트리거가 실행될 때 수행되는 SQL 문입니다. 예를 들어, 레코드 삽입 시 해당 레코드를 감사 테이블에 기록하는 작업을 정의할 수 있습니다.

트리거의 기본 구조

트리거는 데이터베이스마다 문법이 약간씩 다를 수 있지만, 일반적인 구조는 다음과 같습니다:

CREATE TRIGGER trigger_name
BEFORE | AFTER INSERT | UPDATE | DELETE
ON table_name
FOR EACH ROW
BEGIN
    -- 트리거가 실행될 때 수행할 작업
    -- SQL 문 또는 PL/SQL 블록
END;
 
  • trigger_name: 트리거의 이름.
  • BEFORE | AFTER: 트리거가 이벤트 이전에 실행될지, 이후에 실행될지를 결정.
  • INSERT | UPDATE | DELETE: 트리거가 실행될 이벤트 종류.
  • table_name: 트리거가 바인딩되는 테이블.
  • FOR EACH ROW: 트리거가 테이블의 각 행에 대해 실행됨을 의미. 단일 행에 대해 트리거가 실행됨.
  • BEGIN ... END: 트리거가 실행될 때 수행될 작업을 정의하는 SQL 블록.

구성요 설명
선언부(DECLARE) 트리거의 명칭을 정의하는 부분
이벤트부(EVENT) 트리거가 실행되는 타이밍, 이벤트를 명시하는 부분
시작/종료부(BEGIN/END) 트리거의 시작과 종료를 표현, BEGIN/END가 쌍을 이룸. 다수 실행을 제어하는 기본적 단위가 되며 논리적 프로세스를 구성
제어부(CONTROL) 비교적 순차적으로 처리, 비교 조건에 따라 블록 또는 문장을 실행, 조건에 따라 반복 실행
SQL DML을 주로 사용, 자주 사용되지는 않지만 DDL(CREATE, ALTER, DROP, TRUNCATE) 사용
예외부(EXCEPTION) BEGIN ~ END절에서 실행되는 SQL문이 실행될 때 예외 발생 시 예외 처리 방법을 정의하는 처리부

트리거의 주요 용도

  1. 데이터 무결성 유지:
    • 트리거를 사용하여 데이터가 삽입되거나 수정될 때 비즈니스 규칙을 자동으로 적용할 수 있습니다. 예를 들어, 특정 조건이 충족되지 않으면 삽입을 거부하거나 경고 메시지를 발생시킬 수 있습니다.
  2. 데이터 변경 내역 로깅:
    • 테이블의 데이터가 삽입, 수정, 삭제될 때마다 변경 내역을 다른 테이블에 기록하는 트리거를 설정할 수 있습니다. 이를 통해 데이터 감사(audit)를 할 수 있습니다.
  3. 자동 계산 및 값 설정:
    • 트리거를 사용하여 특정 필드의 값을 자동으로 계산하거나 설정할 수 있습니다. 예를 들어, 제품의 가격을 삽입할 때 부가세가 자동으로 계산되어 저장되도록 할 수 있습니다.
  4. 관계된 테이블 업데이트:
    • 데이터베이스의 여러 테이블 간의 관계를 유지하기 위해, 한 테이블의 변경 사항에 따라 다른 테이블도 자동으로 업데이트되도록 할 수 있습니다. 예를 들어, 주문 테이블이 업데이트될 때 재고 테이블도 자동으로 갱신될 수 있습니다.
  5. 제한된 규칙 적용:
    • 특정 조건이 충족되지 않으면 데이터 삽입이나 수정 작업을 거부하거나 수정할 수 있습니다.

NEW와 OLD 키워드

  • NEW: 트리거 내에서 새로 삽입되거나 수정된 값을 참조하는 키워드입니다. INSERT와 UPDATE 트리거에서 사용됩니다.
  • OLD: 기존의 값을 참조하는 키워드입니다. UPDATE와 DELETE 트리거에서 사용됩니다.

예시:

  • INSERT 트리거: NEW만 사용 가능.
  • UPDATE 트리거: NEW와 OLD 모두 사용 가능.
  • DELETE 트리거: OLD만 사용 가능.

트리거의 예시

  1. BEFORE INSERT 트리거:
    • 특정 테이블에 데이터가 삽입되기 전에 값의 유효성을 검증하거나 특정 값을 자동으로 설정.
CREATE TRIGGER check_before_insert
BEFORE INSERT ON employees
FOR EACH ROW
BEGIN
    -- 만약 급여가 0 이하이면 예외를 발생시킴
    IF NEW.salary <= 0 THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '급여는 0보다 커야 합니다.';
    END IF;
END;

 

  1. AFTER UPDATE 트리거:
    • 테이블의 값이 수정된 후, 감사 테이블에 변경 내역을 기록.
CREATE TRIGGER log_employee_update
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN
    INSERT INTO employee_log (employee_id, old_salary, new_salary, change_date)
    VALUES (OLD.id, OLD.salary, NEW.salary, NOW());
END;

 

  1. BEFORE DELETE 트리거:
    • 테이블에서 레코드가 삭제되기 전에 해당 레코드가 다른 테이블에서 참조되고 있는지 확인하는 트리거.
CREATE TRIGGER check_before_delete
BEFORE DELETE ON orders
FOR EACH ROW
BEGIN
    DECLARE order_count INT;
    SELECT COUNT(*) INTO order_count FROM order_items WHERE order_id = OLD.order_id;
    
    -- 만약 주문이 다른 테이블에 참조되고 있으면 삭제를 막음
    IF order_count > 0 THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '이 주문은 삭제할 수 없습니다. 관련된 항목이 있습니다.';
    END IF;
END;

트리거의 장점

  1. 데이터 무결성 강화: 데이터베이스 내에서 무결성 규칙을 자동으로 강제하여 데이터 손상을 방지할 수 있습니다.
  2. 자동화: 데이터 변경 시 자동으로 실행되므로, 데이터베이스 내에서 많은 작업을 자동화할 수 있습니다.
  3. 비즈니스 로직 강제: 데이터를 조작할 때 비즈니스 로직을 강제할 수 있으며, 데이터가 잘못된 방식으로 변경되는 것을 방지할 수 있습니다.
  4. 변경 로그 기록: 데이터베이스 내에서 모든 데이터 변경 내역을 기록하는데 유용합니다.

트리거의 단점 및 주의사항

  1. 성능 문제: 트리거가 자주 실행되면 성능에 영향을 줄 수 있습니다. 특히 복잡한 로직이 트리거 내에서 실행되면 데이터 삽입, 수정, 삭제 속도가 느려질 수 있습니다.
  2. 디버깅 어려움: 트리거는 백그라운드에서 자동으로 실행되기 때문에, 문제가 발생할 경우 그 원인을 찾기가 어렵습니다.
  3. 의존성 증가: 트리거를 과도하게 사용하면 데이터베이스 구조에 의존성이 생길 수 있으며, 시스템 유지보수가 어려워질 수 있습니다.
  4. 복잡성 증가: 데이터가 트리거에 의해 여러 테이블로 확산되면, 데이터 흐름을 추적하기 어려워질 수 있습니다.

트리거 사용 시 주의할 점

  1. 트리거의 로직을 단순하게 유지: 복잡한 로직은 성능에 악영향을 줄 수 있으므로, 트리거 안에서 지나치게 많은 작업을 하지 않도록 주의해야 합니다.
  2. 순환 트리거 방지: 트리거가 또 다른 트리거를 호출하여 무한 루프를 발생시키지 않도록 해야 합니다.
  3. 성능 모니터링: 트리거가 자주 실행되는 경우, 성능 저하가 발생할 수 있으므로 이를 모니터링하고 필요에 따라 최적화해야 합니다.
728x90
반응형

댓글