# 스토어드 프로그램 예외 발생 정리
Programming 2017. 10. 27. 11:56이 글은 이성욱 저, 『개발자와 DBA를 위한 Real MySQL』, 위키북스 교재의 스토어드 프로그램중 예외 처리 부분을 정리한 내용이다.
※ SQLSTATE와 Error No
■ ERROR-NO
- 4자리 숫자값으로 구성된 에러코드로, MySQL에서만 유효한 에러 식별번호
■ SQL-STATE
- 다섯 글자의 알파벳과 숫자로 구성되며, 에러뿐 아니라 여러 가지 상태를 의미하는 코드
→ 반드시 문자열로 입력해야 함
- DBMS 종류가 다르다 하더라도 ANSI SQL 표준을 준수하는 DBMS에서는 모두 똑같은 값과 의미를 가짐
- 대부분의 MySQL 에러 번호는 특정 SqlState 값과 매핑돼 있으며, 매핑되지 않는 ErrorNo는 SqlState값이 “HY000”(General error)으로 설정
- SqlState값의 앞 2글자는 다음과 같은 의미를 가진다.
“00” | - 정상 처리됨 (에러 아님) |
“01” | - 경고 메시지(Warning) |
“02” | - Not found - SELECT나 Cursor에서 결과가 없는 경우에만 사용 |
- 에러 메시지의 목록은 아래의 MySQL메뉴얼에서 확인 가능
- https://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html
※ 핸들러
DECLARE ①handler_type HANDLER FOR ②condition_value [, condition_value] ... ③handler_statements |
■ handler_type
EXIT | - 정의된 handler_statements를 실행한 뒤에 이 핸들러가 정의된 BEGIN…END 블록을 벗어남 - 현재 핸들러가 최상위 BEGIN…END 블록에 정의됐다면 현재 스토어드 프로그램을 벗어나서 종료 - 스토어드 함수에서 EXIT 핸들러가 정의된다면 이 핸들러의 handler_statements 부분에서는 반드시 함수의 반환 타입에 맞는 적절한 값을 반환하는 코드가 포함되어야 함 |
CONTINUE | - handler_statements를 실행하고 스토어드 프로그램의 마지막 실행 지점으로 다시 돌아가 나머지 코드를 처리 |
■ condition_value
SQLSTATE | - 스토어드 프로그램이 실행되는 도중 어떤 이벤트가 발생했을 때 해당 이벤트의 SQLSTATE 값이 일치할 때 실행되는 핸들러를 정의할 때 사용 | ||||||||
SQLWARNING | - 스토어드 프로그램에서 코드를 실행하던 도중 경고(SQL Warning)가 발생했을 때 실행되는 핸들러를 정의할 때 사용 - SQLSTATE값이 01로 시작하는 이벤트를 의미
| ||||||||
NOT FOUND | - SELECT 쿼리문의 결과 건수가 1건도 없거나, CURSOR의 레코드를 마지막까지 읽은 뒤에 실행하는 핸들러를 정의할 때 사용 - SQLSTATE값이 02로 시작하는 이벤트 의미 | ||||||||
SQLEXCEPTION | - SQL Warning와 NOT FOUND 그리고 00(정상 처리)으로 시작하는 SQLSTATE 이외의 모든 케이스를 의미 |
■ CONDITION을 생성하고 그 CONDITION의 이름을 명시할 수도 있음
■ condition_value는 구분자(,)를 이용해 여러 개를 동시에 나열할 수도 있음
■ “00000”인 SQLSTATE와 에러 번호 0은 모두 정상적으로 처리되었음을 의미하므로 condition_value에 사용해서는 안됨
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET error_flag=1; |
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; SELECT ‘Error occurred – terminating’; END;; |
DECLARE CONTINUE HANDLER FOR 1022, 1062 SELECT ‘Duplicate key in index’; |
DECLARE CONTINUE HANDLER FOR NOT FOUND SET process_done=1; |
DECLARE CONTINUE HANDLER FOR SQLSTATE ‘02000’ SET process_done=1; |
DECLARE CONTINUE HANDLER FOR 1329 SET process_done=1; |
DECLARE EXIT HANDLER FOR SQLWARNING, SQLEXCEPTION BEGIN ROLLBACK; SELECT ‘Process terminated, Because error’; SHOW ERRORS; SHOW WARNING; END;; |
※ 컨디션
DECLARE condition_name CONDITION FOR condition_value |
■ condition_name : 부여하려는 이름을 단순 문자열로 입력
■ condition_value
- MySQL의 에러 번호를 사용할 때는 condition_value에 바로 MySQL의 에러 번호를 입력
- 컨디션을 정의할 때는 에러 코드의 값을 여러 개 동시에 명시할 수 없음
- SQLSTATE를 명시하는 경우 SQLSTATE 키워드를 입력하고 그 뒤에 SQLSTATE값을 입력
DECLARE dup_key CONDITION FOR 1062; |
DELIMITER ;; CREATE FUNCTION sf_testfunc() RETURNS BIGINT BEGIN DECLARE dup_key CONDITION FOR 1062; DECLARE EXIT HANDLER FOR dup_key BEGIN RETURN –1; END;
INSERT INTO tb_test VALUES (1); RETURN 1; END ;; |
※ 시그널 (딱히 정리할 개념이 없으므로 예제만 기록)
BEGIN DECLARE null_divisor CONDITION FOR SQLSTATE '45000'; IF p_divisor IS NULL THEN SIGNAL null_divisor SET MESSAGE_TEXT='Divisor can not null', MYSQL_ERRNO=9999; ELSEIF p_divisor = 0 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Divisor can not be 0', MYSQL_ERRNO=9998;
ELSEIF p_dividend IS NULL THEN # 에러가 아닌 경고를 일으킴 SIGNAL SQLSTATE '01000' SET MESSAGE_TEXT='Dividend is null, so regarding dividend as 0', MYSQL_ERRNO=9997; RETURN 0; END IF; RETURN FLOOR(p_dividend / p_visor); END |
> ERROR 9999 (45000): Divisor can not be null > ERROR 9998 (45000): Divisor can not be 0 > 세 번째 조건문의 경우에는 SELECT sf_divide(NULL, 1);을 입력하면 경고 메시지가 발생해야 하는데 어쩐지 발생하지 않는다. |
'Programming' 카테고리의 다른 글
# 1의 보수, 2의 보수, 부동소수점과 바이어스(bias) 표현 (0) | 2017.11.01 |
---|---|
#가변 할당 기반 교체 기법 (1) | 2017.10.30 |
#대칭키와 공개키 (0) | 2017.10.26 |
#쿠키와 세션의 차이 (0) | 2017.10.25 |
#프로세스 스케줄링 (0) | 2017.10.19 |