13.6.7.2 DECLARE ... HANDLER 구문
DECLAREhandler_actionHANDLER FORcondition_value[,condition_value] ...statementhandler_action: CONTINUE | EXIT | UNDOcondition_value:mysql_error_code| SQLSTATE [VALUE]sqlstate_value|condition_name| SQLWARNING | NOT FOUND | SQLEXCEPTION
DECLARE ... HANDLER 문은 하나 이상의 조건을 처리하는 핸들러를 지정합니다. 이러한 조건 중 하나가 발생하면, 지정된 statement 가 실행됩니다. statement 는 SET 등의 간단한 명령문은 var_name = valueBEGIN 과 END 를 사용하여 작성된 복합 문이 될 수 있습니다 ( 섹션 13.6.1 "BEGIN ... END 복합 문"부분 을 참조하십시오) .
핸들러 선언은 변수 나 조건 선언 다음에 지정해야합니다.
handler_action 값은 핸들러 문을 실행 한 후 핸들러가 어떤 작업을 수행하는 방법을 보여줍니다.
CONTINUE: 현재 프로그램의 실행이 계속됩니다.EXIT:이 핸들러가 선언 된BEGIN ... END복합 명령문의 실행이 종료됩니다. 이것은이 조건이 내부의 블록에서 발생하는 경우에도 마찬가지입니다.UNDO: 지원되지 않습니다.
DECLARE ... HANDLER 의 condition_value 이 핸들러를 활성화하는 구체적인 조건 또는 조건의 클래스를 나타냅니다.
MySQL 오류 코드 (번호) 또는 SQLSTATE 값 (5 문자열 리터럴). MySQL 오류 코드 0 또는
'00'로 시작하는 SQLSTATE 값은 오류 조건이 아닌 성공을 설명하기 위해 사용해서는 없습니다. MySQL 오류 코드 및 SQLSTATE 값의 목록은 섹션 B.3 "서버 오류 코드 및 메시지" 를 참조하십시오.이전에
DECLARE ... CONDITION에서 지정된 조건 이름. 조건 이름은 MySQL 오류 코드 또는 SQLSTATE 값에 연결할 수 있습니다. 섹션 13.6.7.1 "DECLARE ... CONDITION 구문" 을 참조하십시오.SQLWARNING는'01'로 시작하는 SQLSTATE 값 클래스의 줄임말입니다.NOT FOUND는'02'로 시작하는 SQLSTATE 값 클래스의 줄임말입니다. 이것은 커서의 컨텍스트에 관계하고 커서가 데이터 세트의 끝에 도달했을 때의 동작을 제어하는 데 사용합니다. 그 이상의 행을 취득 할 수없는 경우 SQLSTATE 값'02000'에서 "데이터 없음"상황이 발생합니다. 이 상황을 감지하려면 그 상황 (또는NOT FOUND상황)의 핸들러를 설정할 수 있습니다. 예를 들어, 섹션 13.6.6 "커서" 를 참조하십시오. 이 상황은 행이 검색되지 않는SELECT ... INTO문에서도 발생합니다.var_listSQLEXCEPTION은'00','01'또는'02'로 시작하지 않는 SQLSTATE 값 클래스의 줄임말입니다.
조건이 발생했을 때 서버가 핸들러를 선택하는 방법은 섹션 13.6.7.6 "핸들러의 범위에 관한 규칙" 을 참조하십시오.
해당 핸들러가 선언되지 않은 조건이 발생하는 경우 수행되는 작업은 그 조건의 클래스에 따라 다릅니다.
SQLEXCEPTION조건의 경우EXIT핸들러가 존재하는 것처럼 저장된 프로그램은 그 조건을 발생시킨 문으로 종료합니다. 그 프로그램이 다른 저장 프로그램에서 호출 된 경우 호출 프로그램이 자신의 핸들러에 적용되는 핸들러 선택 규칙을 사용하여 조건을 처리합니다.SQLWARNING조건의 경우CONTINUE핸들러가 존재하는 것처럼 프로그램 실행을 계속합니다.NOT FOUND조건에서는 그 조건이 정상적으로 발생했을 경우, 액션은CONTINUE입니다.SIGNAL또는RESIGNAL의해 발생했을 경우, 액션은EXIT입니다.
다음 예제에서는 중복 키 에러를 발생시킨다 SQLSTATE '23000' 의 핸들러를 사용합니다.
mysql>CREATE TABLE test.t (s1 INT, PRIMARY KEY (s1));Query OK, 0 rows affected (0.00 sec) mysql>delimiter //mysql>CREATE PROCEDURE handlerdemo ()->BEGIN->DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;->SET @x = 1;->INSERT INTO test.t VALUES (1);->SET @x = 2;->INSERT INTO test.t VALUES (1);->SET @x = 3;->END;->//Query OK, 0 rows affected (0.00 sec) mysql>CALL handlerdemo()//Query OK, 0 rows affected (0.00 sec) mysql>SELECT @x//+------+ | @x | +------+ | 3 | +------+ 1 row in set (0.00 sec)
이 프로 시저를 실행 한 후 @x 가 3 으로되어 있는지 확인하십시오. 이 오류가 발생한 후 프로 시저의 마지막까지 계속 실행되었음을 보여줍니다. DECLARE ... HANDLER 문이 존재하지 않았다고하면 PRIMARY KEY 제약으로 인해 두 번째 INSERT 가 실패한 후에 MySQL은 기본 동작 ( EXIT )을 실행하기 위해 SELECT @x 는 2 를 반환했습니다 했다.
조건을 무시하려면 그 조건의 CONTINUE 핸들러를 선언하고 그것을 빈 블록에 연결합니다. 예 :
DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN END;
블록 레이블 범위는 블록 내에서 선언 된 핸들러의 코드는 포함되지 않습니다. 따라서 핸들러에 연결된 문은 ITERATE 또는 LEAVE 를 사용하여 처리기 선언을 둘러싸고 블록의 라벨을 참조 할 수 없습니다. REPEAT 블록에 retry 레이블이 포함 된 다음의 예를 생각해 보겠습니다.
CREATE PROCEDURE p () BEGIN DECLARE i INT DEFAULT 3; retry : REPEAT BEGIN DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN ITERATE retry; # illegal END; IF i <0 THEN LEAVE retry; # legal END IF; SET i = i - 1; END; UNTIL FALSE END REPEAT; END;
retry 레이블은 블록의 IF 문 범위 내에 있습니다. CONTINUE 핸들러의 범위 내에 않기 때문에 거기에 대한 참조는 무효이며, 오류가 발생합니다.
ERROR 1308 (42000) : LEAVE with no matching label : retry
핸들러의 외부 레이블에 대한 참조를 해결하려면 다음 방법 중 하나를 사용합니다.
이 블록을 떠나기에는
EXIT핸들러를 사용합니다. 블록의 정리가 필요없는 경우는BEGIN ... END처리기 본체를 비울 수 있습니다.DECLARE EXIT HANDLER FOR SQLWARNING BEGIN END;그렇지 않은 경우, 핸들러 본체 내에 정리 문을 배치합니다.
DECLARE EXIT HANDLER FOR SQLWARNING BEGIN
block cleanup statementsEND;실행을 계속하려면
CONTINUE핸들러 내에 둘러싸고있는 블록에서 확인하여 그 핸들러가 호출되었는지 여부를 판정 할 수있는 상태 변수를 설정합니다. 다음 예제에서는 이러한 목적에 변수done을 사용합니다.CREATE PROCEDURE p () BEGIN DECLARE i INT DEFAULT 3; DECLARE done INT DEFAULT FALSE; retry : REPEAT BEGIN DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN SET done = TRUE; END; IF done OR i <0 THEN LEAVE retry; END IF; SET i = i - 1; END; UNTIL FALSE END REPEAT; END;