1. 트리거란?
특정 이벤트 (Insert, Update, Delete)가 발생할 때 자동으로 실행되는 SQL 코드이다.
주로 자동화, 로깅, 데이터 정합성을 유지하기 위해 사용된다.
2. 트리거 기본 문법
트리거 생성
CREATE TRIGGER 트리거이름
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON 테이블명
FOR EACH ROW
BEGIN
-- 실행할 SQL
END;
트리거 조회
SHOW TRIGGERS;
2-1. Before / After 차이
쿼리문의 실행 전에 트리거를 작동할지, 실행 후에 트리거를 작동할지 정하는 구간이다.
Before : 트리거가 걸린 원래 테이블에 쿼리가 실행되기 전
After : 트리거가 걸린 원래 테이블에 쿼리가 실행된 후
3. 실제 예시
3-1. Insert 예시
예를 들어 'tset' 테이블에 insert 작업이 진행될 경우 트리거 테이블에 'insert' 라는 값과 'key' 값을 자동으로 적용하는 트리거를 작성하겠다.
DELIMITER $$ # ';' 를 '$$' 기호로 변경하여 인식
CREATE TRIGGER trg_test_insert
AFTER INSERT ON test #'test' 테이블에 Insert 후
FOR EACH ROW
BEGIN
INSERT INTO trig_test(ACTION, DOCID) # 'trig_test' 테이블의 Action, DOCID 값을
VALUES ('insert', NEW.Key); # 'insert'와 'test' 테이블에 insert될 key 값을 같이 insert, 이후 ';'로 쿼리 종료
END$$ # '$$' 로 바꿔주었기 때문에 '$$'로 진짜 종료
DELIMITER ; # 다시 ';'로 변경
위의 트리거는 test테이블에 insert 작업이 발생할 경우
test 테이블의 Key 값을 trig_test 의 DOCID 값으로 insert 하는 트리거 쿼리문이다.
3-2. 조건이 추가된 update
DELIMITER $$
CREATE TRIGGER trg_test_update_delete
AFTER UPDATE ON test
FOR EACH ROW
BEGIN
IF NEW.ACTION = 'delete' AND OLD.ACTION != 'delete' THEN # test 테이블의 기존 Action 값이 delete가 아닌데, 새로운 값이 delete로 업데이트 될 경우
UPDATE trig_test
SET ACTION = 'delete' # delete로 update
WHERE DOCID = NEW.Key;
ELSE # 위의 IF문의 예외 경우
UPDATE trig_test
SET ACTION = 'update' # update로 update
WHERE DOCID = NEW.Key;
END IF;
END$$
DELIMITER ;
test 테이블에서 delete로 값이 변경될 경우 trig_test 테이블에도 delete 값으로 변경해주고
그 외의 경우에는 update 값으로 변경해주는 쿼리문이다.
OLD와 NEW는 무엇인가요
OLD/NEW는 트리거가 작동하는 시점의 데이터 값을 참조하는 키워드이다.
OLD는 변경 이전의 값
NEW는 변경 이후의 값이다.
따라서, NEW는 INSERT와 UPDATE에서 사용할 수 있고, (DELETE 사용 x)
OLD는 UPDATE와 DELETE에서 사용할 수 있다. (INSERT 사용 x)
5. 주의사항 및 한계
1. 트리거 중복 불가
하나의 테이블에 여러개의 INSERT/UPDATE/DELETE트리거를 중복해서 생성할 수 없다.
예를들어 위의 예시와 같이 INSERT시 적용되는 trg_test_insert 트리거를 생성하였다.
해당 건은 insert가 발생할 경우 'insert' 값을 넣는 트리거이다.
이후 다른 값을 넣고 싶어 trg_test_insert2를 선언할 경우 오류와 함께 생성되지 않는다.
이와 마찬가지로 위의 trg_test_update_delete를 나눠서 trg_test_update로 생성하고, trg_test_delete로 별도로 생성하려해도 안된다.
하나의 update만 존재할 수 있기 때문이다.
결론: 각 이벤트마다 (INSERT, UPDATE, DELETE) 1개의 트리거만 생성이 가능하다.
그러므로 필요에 따라 IF ~ THEN ~ 같은 분기 조건문의 사용이 필수가 된다.
2. 외부 시스템 호출 불가.
트리거 내부에서는 HTTP요청, 파일 입출력, 시스템 명령어 등 실행이 불가능 하다.
따라서 필요하다면, 트리거 > 로그 테이블 기록 > 외부 앱에서 감지 및 처리 구조가 필요하다.
3. 중첩 실행 불가 / 재귀 호출 / 무한 반복 주의
트리거 안에서 동일한 테이블을 조작하면 무한루프에 빠질 수 있으니 조심해야 한다.
-- 이런 식으로 같은 테이블에 다시 INSERT하면 무한 루프 발생 가능
AFTER INSERT ON users → 다시 INSERT INTO users
4. 성능 저하 가능성
트리거는 자동으로 실행되기 때문에 성능 저하 발생 가능성이 존재한다.
사실 당연한 말이지만
복잡한 로직을 담고있는 트리거나, 무수히 많은 양의 데이터 처리가 발생될 경우 성능 저하가 발생할 수 있다.
5. 디버깅 어려움
트리거 내부에서 오류가 발생해도, 발생 위치를 확인하기 어렵다.
따라서, 트리거 안에는 최대한 단순한 로직을 담는것이 좋다.
'DB > MySQL' 카테고리의 다른 글
[프로그래머스] MySQL 자동차 대여 기록 별 대여 금액 구하기 (1) | 2023.11.24 |
---|---|
[프로그래머스] MySQL - 오랜 기간 보호한 동물(2) (0) | 2023.11.24 |
[프로그래머스] MySQL - 대여 횟수가 많은 자동차들의 월별 대여 횟수 구하기 (1) | 2023.11.24 |
[Mysql] 프로그래머스 특정 기간동안 대여 가능한 자동차들의 대여비용 구하기 (0) | 2023.09.19 |
[Mysql] 별칭(alias) 정렬 (0) | 2023.09.15 |
댓글