트리거 Trigger는 INSERT, UPDATE, DELETE 구문이 수행될 때 자동으로 호출되는 프로시저를 의미합니다. 일반적으로 프로시저는 CALL을 통해 명시적으로 호출해야 실행되었지만, 트리거는 등록만 해두면 해당 명령이 실행될 때 자동으로 호출된다는 특징을 갖습니다.
DBMS 마다 트리거의 동작이 살짝 다르지만 여기서는
MySQL을 기준으로 설명합니다.
트리거는 데이터 조작이 수행되기 전인 BEFORE와 데이터 조작이 수행된 후의 AFTER 두 가지 시점(타이밍)에 수행되도록 만들 수 있습니다.
트리거는 CREATE TRIGGER 구문을 통해서 정의합니다.
트리거는 실행 방법에서만 차이를 보이는 프로시저의 일종이므로 여기서는 트리거에서 사용되는 주요 정의만 살펴봅니다. 프로시저의 기본 정의에 대해서는 이전 포스트를 참조해주세요.
DELIMITER $$
CREATE TRIGGER 트리거_이름
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON 트리거_동작_대상_테이블
FOR EACH ROW
BEGIN
#트리거 내부 SQL
END $$
DELIMITER ;
프로시저와 동일하게 BEGIN-END 블록에 트리거 실행 시 수행될 SQL 구문을 작성합니다. 선언부를 조금 더 자세히 살펴보면 다음과 같습니다.
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON 트리거_동작_대상_테이블
FOR EACH ROW
BEFORE, AFTER를 통해 INSERT, UPDATE, DELETE 명령의 수행 전/후로 트리거가 발동되도록 지정합니다.ON 이후로 어떤 테이블에서 데이터 조작이 실행되면 트리거를 발동시킬지 명시합니다.FOR EACH ROW는 각 행이 INSERT, UPDATE, DELETE 된 후 트리거를 수행한다는 것을 명시합니다.오라클 등의 데이터베이스에서는
FOR EACH STATEMENT와 같은 단위도 지원하지만MySQL에서는 오직FOR EACH ROW행 단위 트리거만 지원합니다.

위와같은 예시 테이블을 두 개 만들었습니다. numbers_table에 데이터를 INSERT하면 sub_numbers_table에 numbers_table에 삽입한 데이터에 10을 더한 데이터를 INSERT하는 트리거를 작성해보겠습니다.
DELIMITER $$
CREATE TRIGGER trg_after_insert_numbers
AFTER INSERT
ON db_test.numbers_table
FOR EACH ROW
BEGIN
INSERT INTO db_test.sub_numbers_table (sn_id, sn_data)
VALUES (NEW.n_id, NEW.n_data + 10);
END $$
DELIMITER ;
명시적 호출이 필요한 트리거와 다르게 INSERT가 수행되면 호출되게 만들었으므로 numbers_table에 INSERT 구문이 발생하면 INSERT 수행 후에 트리거가 실행됩니다.
한 번 실제로 데이터를 삽입해보겠습니다.
INSERT INTO numbers_table (n_data)
VALUES (1);


numbers_table에만 데이터를 삽입했는데 트리거를 통해 자동적으로 sub_numbers_table에도 데이터가 삽입된 것을 알 수 있습니다.
데이터를 삽입할 때 보시면 NEW라는 키워드가 들어가있는데요. 이는 컬럼의 값이 참조할 대상을 가리키는 키워드로 NEW, OLD 두 가지가 있습니다.
NEW: 트리거 실행 시점에 삽입, 갱신되는 새로운 레코드의 컬럼값 참조OLD: 트리거 실행 시점에 삭제, 갱신되는 기존의 레코드 컬럼값 참조NEW, OLD는 BEFORE, AFTER와 INSERT, UPDATE, DELETE 중 어떤 트리거를 생성하느냐에 따라서 사용 가능 여부가 달라집니다.
| 이벤트 | BEFORE 트리거 | AFTER 트리거 |
|---|---|---|
| INSERT | NEW 사용 가능OLD 사용 불가 | NEW 사용 가능OLD 사용 불가 |
| UPDATE | NEW, OLD 모두 사용 가능 | NEW, OLD 모두 사용 가능 |
| DELETE | OLD 사용 가능NEW 사용 불가 | OLD 사용 가능NEW 사용 불가 |