MySQL 저장 프로시저를 사용하다 보면 예외(exception)가 발생하는 상황을 자주 마주하게 됩니다. 이때 적절한 오류 메시지를 통해 예외를 처리하지 않으면, 해당 예외로 인해 애플리케이션 전체가 실패할 위험이 있습니다. 다행히 MySQL은 오류 메시지를 출력하면서도 실행을 계속 진행할 수 있는 핸들러(handler) 기능을 제공합니다.
CONTINUE HANDLER란?
DECLARE CONTINUE HANDLER는 저장 프로시저 내에서 SQL 예외가 발생했을 때 지정한 동작을 수행한 뒤, 프로시저의 나머지 코드를 계속 실행하도록 만드는 구문입니다. 아래 예제에서는 Primary Key 컬럼에 중복된 값을 삽입하려는 상황을 통해 이 핸들러의 동작을 확인해 보겠습니다.
핸들러를 활용한 저장 프로시저 예제
mysql> DELIMITER //
mysql> Create Procedure Insert_Studentdetails(S_Studentid INT, S_StudentName Varchar(20), S_Address Varchar(20))
-> BEGIN
-> DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SELECT 'Got an error';
-> INSERT INTO Student_detail
-> (Studentid, StudentName, Address)
-> Values(S_Studentid,S_StudentName,S_Address);
-> Select * from Student_detail;
-> END //
Query OK, 0 rows affected (0.19 sec)
위 프로시저에서 핵심은 다음 구문입니다.
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SELECT 'Got an error';
이 구문은 SQL 예외가 발생하면 'Got an error'라는 메시지를 출력하고, 프로시저 실행을 중단하지 않고 계속 진행하라는 의미입니다.
프로시저 호출 및 결과 확인
이제 위에서 생성한 프로시저를 호출해 보겠습니다. 'studentid' 컬럼에 중복된 값을 입력하려고 하면 'Got an error'라는 오류 메시지가 출력되지만, 실행은 중단되지 않고 계속 진행됩니다.
mysql> Delimiter ;
mysql> CALL Insert_Studentdetails(100, 'Gaurav', 'Delhi');
+-----------+-------------+---------+
| Studentid | StudentName | address |
+-----------+-------------+---------+
| 100 | Gaurav | Delhi |
+-----------+-------------+---------+
1 row in set (0.11 sec)
mysql> CALL Insert_Studentdetails(101, 'Raman', 'Shimla');
+-----------+-------------+---------+
| Studentid | StudentName | address |
+-----------+-------------+---------+
| 100 | Gaurav | Delhi |
| 101 | Raman | Shimla |
+-----------+-------------+---------+
2 rows in set (0.06 sec)
여기까지는 정상적으로 데이터가 삽입됩니다. 그다음 이미 존재하는 학번 101을 다시 삽입해 보면 어떻게 되는지 살펴보겠습니다.
mysql> CALL Insert_Studentdetails(101, 'Rahul', 'Jaipur');
+--------------+
| Got an error |
+--------------+
| Got an error |
+--------------+
1 row in set (0.03 sec)
+-----------+-------------+---------+
| Studentid | StudentName | address |
+-----------+-------------+---------+
| 100 | Gaurav | Delhi |
| 101 | Raman | Shimla |
+-----------+-------------+---------+
2 rows in set (0.04 sec)
중복 키 오류가 발생하자 핸들러가 동작하여 'Got an error' 메시지를 출력했습니다. 하지만 프로시저는 멈추지 않고 바로 다음 문장인 Select * from Student_detail;을 실행하여 현재 테이블의 전체 데이터를 조회했습니다. 즉, INSERT는 실패했지만 SELECT는 정상적으로 수행된 것입니다.
mysql> CALL Insert_Studentdetails(103, 'Rahul', 'Jaipur');
+-----------+-------------+---------+
| Studentid | StudentName | address |
+-----------+-------------+---------+
| 100 | Gaurav | Delhi |
| 101 | Raman | Shimla |
| 103 | Rahul | Jaipur |
+-----------+-------------+---------+
3 rows in set (0.08 sec)
중복되지 않는 새로운 값(103)을 삽입하면 오류 없이 정상적으로 처리되는 것도 확인할 수 있습니다.
정리
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION을 사용하면 저장 프로시저에서 예외가 발생해도 프로시저가 비정상 종료되지 않고, 사전에 정의한 오류 메시지를 출력한 뒤 남은 로직을 계속 수행할 수 있습니다. 이를 활용하면 대량의 데이터를 일괄 처리할 때 특정 레코드의 오류가 전체 작업 실패로 이어지는 것을 방지할 수 있어 실무에서 매우 유용합니다.