Tech

Diary

Lecture

About Me

개발중

trigger

JeongSeulho

2025년 01월 11일

준비중...
클립보드로 복사

trigger

  • DB에서 어떤 이벤트가 발생하면 자동적으로 실행되는 프로시저
  • 여기서 이벤트는 INSERT, UPDATE, DELETE 등의 데이터 변경

로그 자동 저장에 활용

  • 유저가 닉네임을 변경하면 변경 전 닉네임의 로그를 저장하는 트리거
copy
CREATE TRIGGER log_user_nickname_trigger -- 트리거 이름
BEFORE UPDATE -- 트리거 실행 시점
ON users FOR EACH ROW -- 트리거 기준 테이블과 실행 범위
BEGIN
    INSERT INTO user_nickname_logs -- 실행할 프로시저
    VALUES (OLD.id, OLD.nickname, NOW()); -- OLD는 UPDATE 전의 tuple을 가리킴
END
$$

누적 테이블 업데이트에 활용

  • 상품 구매마다 유저별 총 사용한 금액 누적
copy
CREATE TRIGGER sum_buy_prices_trigger
AFTER INSERT
ON buy FOR EACH ROW
BEGIN
    DECLARE total INT;
    DECLARE user_id INT DEFAULT NEW.user_id; -- NEW는 INSERT된 tuple을 가리킴, DECLARE로 선언과 동시에 DEFAULT 값을 할당

    SELECT SUM(price) INTO total FROM buy WHERE user_id = user_id; -- INTO 키워드로 쿼리 결과를 변수에 할당
    UPDATE user_total_stats SET price_sum = total WHERE user_id = user_id; -- 변수를 이용해 누적 테이블 업데이트
END
$$

여러 데이터 변경을 한번에 감지

  • 단 MYSQL에서는 불가능 하므로 postgreSQL를 기준으로 예시
copy
CREATE TRIGGER avg_empl_salary_trigger
AFTER INSERT OR UPDATE OR DELETE -- 여러 데이터 변경을 한번에 감지
ON employee FOR EACH ROW
    EXECUTE FUNCTION avg_empl_salary(); -- 실행할 함수
$$
  • 하지만 위 예시에서 해당 employee 테이블에 모든 튜플을 수정하면 트리거가 여러번 실행되는 문제가 있음
  • 예를들어 직원이 5명이 있고 이를 모두 수정하면 수정 마다 트리거 실행(FOR EACH ROW 때문)

FOR EACH STATEMENT

  • 트리거 실행 범위를 튜플 단위가 아닌 문장 단위로 지정
copy
CREATE TRIGGER avg_empl_salary_trigger
AFTER INSERT OR UPDATE OR DELETE
ON employee FOR EACH STATEMENT
    EXECUTE FUNCTION avg_empl_salary();
$$

WHEN 조건으로 트리거 실행 제한

  • 사용자가 기존 닉네임과 다른 닉네임으로 변경했을 때만 트리거 실행
copy
CREATE TRIGGER log_user_nickname_trigger
BEFORE UPDATE
ON users FOR EACH ROW
WHEN (NEW.nickname IS DISTINCT FROM OLD.nickname)
BEGIN
    INSERT INTO user_nickname_logs VALUES (OLD.id, OLD.nickname, NOW());
END
$$

trigger 주의 사항

  • 트리거 자체는 코드상에서 확인이 어렵고 디버깅이 어려움
  • 고도한 트리거는 DB에 부하를 줄 수 있음
  • 문서화가 중요함