Computer >> 컴퓨터 >  >> 프로그래밍 >> MySQL

MySQL 트리거에서 FOR EACH ROW는 어떻게 작동할까? 핵심 개념과 예제

MySQL에서 FOR EACH ROW는 말 그대로 UPDATE 또는 DELETE 문에 의해 영향을 받는(매칭되는) 각 행(row)마다 트리거 본문이 실행된다는 의미입니다. 즉, 트리거가 테이블 전체에 딱 한 번 적용되는 것이 아니라, 조건에 해당하는 행의 수만큼 트리거 본문이 반복해서 실행됩니다.

이 개념은 실제 예제를 통해 훨씬 명확하게 이해할 수 있습니다. 아래에서 삭제되는 각 행마다 트리거가 어떻게 동작하는지 단계별로 살펴보겠습니다.

예제를 위한 테이블 준비

먼저 예제에 사용할 두 개의 테이블, 즉 원본 데이터를 담을 Sample 테이블과 영향받은 행 수를 기록할 Sample_rowaffected 테이블을 생성합니다.

mysql> Create table Sample(id int, value varchar(20));
Query OK, 0 rows affected (0.47 sec)

mysql> Insert into Sample(id, value) values(100, 'same'),(101,
'Different'),(500, 'excellent'),(501, 'temporary');
Query OK, 4 rows affected (0.04 sec)
Records: 4 Duplicates: 0 Warnings: 0

mysql> Select * from Sample;
+------+-----------+
| id   | value     |
+------+-----------+
| 100  | same      |
| 101  | Different |
| 500  | excellent |
| 501  | temporary |
+------+-----------+
4 rows in set (0.00 sec)

mysql> Create table Sample_rowaffected(id int);
Query OK, 0 rows affected (0.53 sec)

mysql> Select Count(*) as 'Rows Affected' from sample_rowaffected;
+---------------+
| Rows Affected |
+---------------+
|             0 |
+---------------+
1 row in set (0.10 sec)

Sample 테이블에는 총 4개의 행이 들어 있고, 아직 Sample_rowaffected 테이블은 비어 있는 상태(영향받은 행 수 0건)입니다.

BEFORE DELETE 트리거 생성

이제 Sample 테이블에서 행이 삭제되기 직전에 실행되는 트리거를 만들어 보겠습니다. 이 트리거는 사용자 변수 @count를 1씩 증가시키고, 그 값을 sample_rowaffected 테이블에 기록합니다.

mysql> Delimiter //
mysql> Create trigger trigger_before_delete_sample BEFORE DELETE on
Sample
    -> FOR EACH ROW
    -> BEGIN
    -> SET @count = if (@count IS NULL, 1, (@count+1));
    -> INSERT INTO sample_rowaffected values (@count);
    -> END ;
    -> //
Query OK, 0 rows affected (0.15 sec)
mysql> Delimiter ;

여기서 주목할 부분은 바로 FOR EACH ROW 구문입니다. 이 구문 덕분에 DELETE 문으로 여러 행이 한꺼번에 삭제되더라도, 삭제되는 각 행마다 BEGIN~END 사이의 트리거 본문이 개별적으로 실행됩니다.

행 삭제 후 결과 확인

다음 쿼리는 Sample 테이블에서 ID가 500 이상인 행들을 삭제하며, 삭제된 행의 개수가 사용자 변수 @count에 저장됩니다.

mysql> Delete from Sample WHERE ID >=500;
Query OK, 2 rows affected (0.11 sec)

mysql> Select @count;
+--------+
| @count |
+--------+
|      2 |
+--------+
1 row in set (0.03 sec)

DELETE 문으로 2개의 행이 삭제되었고, @count 값도 2로 기록되었습니다. 이어서 sample_rowaffected 테이블을 조회해 실제로 트리거가 몇 번 실행되었는지 확인해 보겠습니다.

mysql> Select Count(*) as 'Rows Affected' from sample_rowaffected;
+---------------+
| Rows Affected |
+---------------+
|             2 |
+---------------+
1 row in set (0.00 sec)

mysql> Select * from Sample;
+------+-----------+
| id   | value     |
+------+-----------+
| 100  | same      |
| 101  | Different |
+------+-----------+
2 rows in set (0.00 sec)

결론

위 예제의 결과를 보면 분명해집니다. DELETE 문 하나로 2개의 행이 삭제되었지만, 트리거 본문은 총 2번 실행되어 sample_rowaffected 테이블에 2개의 레코드가 기록되었습니다.

이것이 바로 FOR EACH ROW의 핵심입니다. 트리거는 문(statement) 단위가 아니라 UPDATE 또는 DELETE 등의 DML 문에 의해 매칭되어 변경되는 각 행마다 트리거 본문을 실행합니다. 따라서 영향받는 행이 많을수록 트리거도 그만큼 여러 번 실행된다는 점을 반드시 기억해야 하며, 대량의 데이터를 처리하는 쿼리에서 트리거를 사용할 때는 성능에 미치는 영향도 함께 고려하는 것이 좋습니다.