trigger
JeongSeulho
2025년 01월 11일
준비중...
클립보드로 복사
trigger
- DB에서 어떤 이벤트가 발생하면 자동적으로 실행되는 프로시저
- 여기서 이벤트는 INSERT, UPDATE, DELETE 등의 데이터 변경
로그 자동 저장에 활용
- 유저가 닉네임을 변경하면 변경 전 닉네임의 로그를 저장하는 트리거
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
$$
누적 테이블 업데이트에 활용
- 상품 구매마다 유저별 총 사용한 금액 누적
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를 기준으로 예시
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
- 트리거 실행 범위를 튜플 단위가 아닌 문장 단위로 지정
CREATE TRIGGER avg_empl_salary_trigger
AFTER INSERT OR UPDATE OR DELETE
ON employee FOR EACH STATEMENT
EXECUTE FUNCTION avg_empl_salary();
$$
WHEN 조건으로 트리거 실행 제한
- 사용자가 기존 닉네임과 다른 닉네임으로 변경했을 때만 트리거 실행
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에 부하를 줄 수 있음
- 문서화가 중요함