VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
트리거 만들기
BEFORE 대 AFTER
BEFORE INSERT 트리거는 기본값을 설정하거나 잘못된 데이터를 거부할 수 있습니다. AFTER INSERT 트리거는 삽입이 성공한 뒤 감사 레코드를 쓸 수 있습니다.
NEW와 OLD 참조
쓰이는 내용을 바꾸려면
BEFORE 트리거에서 NEW 값을 수정하세요:
이벤트당 여러 트리거
MySQL은 같은 테이블과 이벤트에 여러 트리거를 지원합니다.FOLLOWS와 PRECEDES 키워드가 실행 순서를 제어합니다:
FOLLOWS/PRECEDES가 없으면 MySQL은 생성 시각에 따라 실행 순서를 배정합니다.
트리거에서 오류 발생시키기
작업을 중단하고 호출자에게 오류를 반환하려면SIGNAL을 사용하세요:
BEFORE 트리거가 오류를 시그널하면 삽입/갱신/삭제는 중단됩니다 — 아무것도 쓰이지 않습니다.
트리거의 제약
MySQL 트리거에는 알아 둘 만한 몇 가지 제약이 있습니다:- 트리거는 결과 집합을 반환하는 스토어드 프로시저를 호출할 수 없습니다
- 트리거는
COMMIT,ROLLBACK,SAVEPOINT를 직접 사용할 수 없습니다 (둘러싼 트랜잭션에 참여합니다) - 트리거는 자신이 정의된 테이블을 참조할 수 없습니다 (대부분의 맥락에서 같은 테이블에 대한 직접 쿼리를 통한 재귀적 트리거 호출은 불가능합니다)
AFTER트리거는NEW값을 수정할 수 없습니다 — 행이 이미 쓰였습니다- MySQL은 문 수준 트리거를 지원하지 않습니다 (모든 트리거는
FOR EACH ROW입니다)
트리거를 사용해야 할 때
트리거는 다음에 잘 맞습니다:- 감사 로깅 — 애플리케이션과 관계없이 누가 무엇을 언제 바꿨는지 기록하기
- CHECK 제약 조건으로 표현할 수 없는 복잡한 제약 강제하기
- 파생 데이터를 동기화 상태로 유지하기 (비정규화된 요약 열, 감사 타임스탬프)
- 로직이 복잡해서 디버깅하려면 숨겨진 부작용을 추적해야 할 때
- 성능이 중요할 때 — 모든 트리거는 영향을 받는 모든 문에서 행마다 실행됩니다
- 트리거가 그 존재를 모르는 애플리케이션 개발자를 놀라게 하는 방식으로 데이터를 수정할 때
자주 묻는 질문
LOAD DATA INFILE 중에도 트리거가 실행되나요?
예.LOAD DATA INFILE이 로드하는 각 행에 대해 INSERT 트리거가 실행됩니다. 트리거가 상당한 작업을 한다면, LOAD DATA를 통한 대량 로드는 먼저 스테이징 테이블에 로드한 다음 INSERT…SELECT로 복사하는 것보다 훨씬 느립니다 (INSERT…SELECT도 트리거를 실행하지만, SET @disable_trigger = TRUE와 트리거 안의 조건 검사로 일시적으로 끌 수 있습니다).
트리거가 스토어드 프로시저를 호출할 수 있나요?
예, 예외 하나가 있습니다: 호출되는 프로시저는 결과 집합(INTO가 없는 SELECT)을 반환할 수 없습니다. 반환하면 MySQL은 오류를 반환합니다. 트리거에서 호출되는 프로시저는 OUT 매개변수와 SELECT...INTO를 사용할 수 있습니다.
REPLACE INTO에서도 트리거가 실행되나요?
REPLACE는 충돌이 있으면 DELETE + INSERT로 실행됩니다. 충돌 시 대상 테이블에서 4개 모두 다음 순서로 실행됩니다: BEFORE INSERT(중복 키 검사), 그다음 충돌하는 행에 대한 BEFORE DELETE와 AFTER DELETE, 그다음 AFTER INSERT. 이 삭제는 실제 행 삭제이므로, 참조하는 테이블의 ON DELETE CASCADE 규칙도 실제로 실행됩니다.
문제 해결
함께 보기
- MySQL의 스토어드 프로시저 — 트리거가 호출할 수 있는 로직
- 트리거에서 웹훅 보내기 — 트리거 본문에서의 HTTP 호출
- MySQL의 CHECK 제약 조건 — 트리거로 자주 구현하는 검증 규칙의 더 단순한 대안