13.6.7.6 핸들러의 범위에 관한 규칙
저장 프로그램은 그 프로그램 내에서 특정 조건이 발생했을 때 호출되는 핸들러를 포함 할 수 있습니다. 각 핸들러의 적용 성 프로그램 정의에 대한 처리기의 장소와 처리기가 처리하는 하나 이상의 조건에 따라 다릅니다.
BEGIN ... END블록 내에 선언 된 처리기는 그 블록 내에서 핸들러 선언 뒤에있는 SQL 문 범위 내 밖에 없습니다. 그 핸들러 자체가 조건을 발생시킨 경우에는 그 핸들러도 그 블록 내에서 선언 된 다른 어떤 핸들러도 그 조건을 처리 할 수 없습니다. 다음 예제에서는 핸들러H1과H2는 문stmt1및stmt2의해 발생한 조건의 범위 내에 있습니다. 그러나H1도H2도H1또는H2의 본체에서 발생한 조건의 범위에는 없습니다.BEGIN - outer block DECLARE EXIT HANDLER FOR ...; - handler H1 DECLARE EXIT HANDLER FOR ...; - handler H2
stmt1;stmt2; END;핸들러는 그것이 선언 된 블록의 범위 밖에없고, 그 블록의 외부에서 발생한 조건에 대해 활성화 할 수 없습니다. 다음 예제에서는 핸들러
H1은 안쪽 블록에있는stmt1의 범위에 있지만, 외부 블록에있는stmt2의 범위에는 없습니다.BEGIN - outer block BEGIN - inner block DECLARE EXIT HANDLER FOR ...; - handler H1
stmt1; END;stmt2; END;핸들러는 특정 핸들러 또는 일반 처리기 중 하나입니다. 특정 핸들러는 MySQL 오류 코드
SQLSTATE값 또는 조건 이름을 처리하기위한 것입니다. 일반 처리기는SQLWARNING,SQLEXCEPTION또는NOT FOUND클래스의 조건을 처리하기위한 것입니다. 나중에 설명되는 바와 같이, 조건의 특이성은 조건의 우선 순위에 관련이 있습니다.
여러 핸들러를 다른 범위 내에서, 또한 다른 특이성으로 선언 할 수 있습니다. 예를 들어, 외부 블록은 특정 MySQL 오류 코드 처리기는 또한 내부 블록에는 일반적인 SQLWARNING 핸들러가있을 수 있습니다. 또는 특정 MySQL 에러 코드의 핸들러와 일반적인 SQLWARNING 클래스의 핸들러가 동일한 블록에있을 수 있습니다.
있는 핸들러가 활성화되는지 여부는 그 자체의 범위와 조건 값뿐만 아니라 다른 어떤 핸들러가 존재하는지에 따라 달라집니다. 저장 프로그램에서 조건이 발생하면 서버는 적용 가능한 핸들러를 현재 범위 (현재 BEGIN ... END 블록) 내에서 검색합니다. 적용 가능한 핸들러가 존재하지 않는 경우는 연속 포함 각 범위 (블록)의 핸들러의 경우 외부 검색을 계속합니다. 특정 범위에서 적용 가능한 핸들러를 하나 이상 발견하면 서버는 다음 조건의 우선 순위에 따라 그 핸들러에서 선택합니다.
MySQL 오류 코드 핸들러는
SQLSTATE값 핸들러보다 우선합니다.SQLSTATE값 핸들러는 일반적인SQLWARNING,SQLEXCEPTION또는NOT FOUND핸들러보다 우선합니다.SQLEXCEPTION핸들러는SQLWARNING핸들러보다 우선합니다.NOT FOUND의 우선 순위는 조건이 어떻게 발생했는지에 따라 다릅니다.일반적으로
NOT FOUND클래스의 조건은SQLWARNING또는NOT FOUND핸들러에서 처리 할 수 있으며, 그 모두가 존재하는 경우SQLWARNING처리기가 사용됩니다.NOT FOUND는 일반적으로 일련의 행을 인출하는 데 사용되는 커서가 데이터 세트의 마지막에 이르렀을 경우 또는WHERE절에서 행을 찾지SELECT ... INTO인스턴스에 대해 발생합니다 .var_listNOT FOUND조건이SIGNAL(또는RESIGNAL) 문에 의해 발생한 경우, 그 조건은NOT FOUND핸들러에서 처리 할 수 있지만,SQLWARNING처리기에서 처리 할 수 없습니다.
같은 우선 순위가 적용 가능한 핸들러가 존재할 가능성이 있습니다. 예를 들어, 문이 각각에 대해 오류 고유의 핸들러가 존재하는 다른 오류 코드를 가진 여러 경고를 생성 할 수 있습니다. 이 경우 서버가 어떤 핸들러를 활성화할지의 선택은 불확정이며, 그 조건이 발생한 상황에 따라 변경 될 수 있습니다.
핸들러 선택 규칙의 하나의 요소는 다양한 적용 가능한 핸들러가 다른 범위에 있으면 가장 로컬 범위의 핸들러가 외부의 범위에있는 핸들러보다 (그것이 더 구체적인 조건 핸들러도) 우선되는 점이 있습니다.
조건이 발생했을 때 적절한 핸들러가 존재하지 않는 경우 수행 할 작업은 그 조건의 클래스에 따라 다릅니다.
SQLEXCEPTION조건의 경우EXIT핸들러가 존재하는 것처럼 저장된 프로그램은 그 조건을 발생시킨 문으로 종료합니다. 그 프로그램이 다른 저장 프로그램에서 호출 된 경우 호출 프로그램이 자신의 핸들러에 적용되는 핸들러 선택 규칙을 사용하여 조건을 처리합니다.SQLWARNING조건의 경우CONTINUE핸들러가 존재하는 것처럼 프로그램 실행을 계속합니다.NOT FOUND조건에서는 그 조건이 정상적으로 발생했을 경우, 액션은CONTINUE입니다.SIGNAL또는RESIGNAL의해 발생했을 경우, 액션은EXIT입니다.
다음 예제는 MySQL이 처리기 선택 규칙이 어떻게 적용되는지를 보여줍니다.
다음 프로 시저에는 2 개의 핸들러가 포함되어 있습니다. 즉, 존재하지 않는 테이블을 제거하려는 시도에 발생하는 특정 SQLSTATE 값 ( '42S02' ) 용으로 하나 일반적인 SQLEXCEPTION 클래스에 대해 하나입니다.
CREATE PROCEDURE p1 () BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SELECT 'SQLSTATE handler was activated'AS msg; DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SELECT 'SQLEXCEPTION handler was activated'AS msg; DROP TABLE test.t; END;
두 핸들러가 동일 블록 내에서 선언 된 동일한 범위를 가지고 있습니다. 그러나 SQLSTATE 핸들러는 SQLEXCEPTION 핸들러보다 우선되기 때문에 테이블 t 가 존재하지 않는 경우, DROP TABLE 문은 SQLSTATE 핸들러를 활성화하는 조건을 발생시킵니다.
mysql> CALL p1();
+--------------------------------+
| msg |
+--------------------------------+
| SQLSTATE handler was activated |
+--------------------------------+
다음 프로 시저에 동일한 2 개의 핸들러가 포함되어 있습니다. 그러나 이번에는 DROP TABLE 문과 SQLEXCEPTION 핸들러가 SQLSTATE 핸들러에 대해서 내부 블록에 있습니다.
CREATE PROCEDURE p2 () BEGIN - outer block DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SELECT 'SQLSTATE handler was activated'AS msg; BEGIN - inner block DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SELECT 'SQLEXCEPTION handler was activated'AS msg; DROP TABLE test.t; - occurs within inner block END; END;
이 경우는 조건이 발생한 장소에 더 로컬 처리기가됩니다. SQLSTATE 핸들러보다 일반적 임에도 불구하고 SQLEXCEPTION 핸들러가 활성화됩니다.
mysql> CALL p2();
+------------------------------------+
| msg |
+------------------------------------+
| SQLEXCEPTION handler was activated |
+------------------------------------+
다음 프로 시저에서는 핸들러의 하나가 DROP TABLE 문 범위에 대해 내부 블록에서 선언되고 있습니다.
CREATE PROCEDURE p3 () BEGIN - outer block DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SELECT 'SQLEXCEPTION handler was activated'AS msg; BEGIN - inner block DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SELECT 'SQLSTATE handler was activated'AS msg; END; DROP TABLE test.t; - occurs within outer block END;
다른 핸들러가 DROP TABLE 에 의해 발생한 조건의 범위에 없기 때문에 SQLEXCEPTION 핸들러 만 적용됩니다.
mysql> CALL p3();
+------------------------------------+
| msg |
+------------------------------------+
| SQLEXCEPTION handler was activated |
+------------------------------------+
다음 프로 시저에서는 두 핸들러가 DROP TABLE 문 범위에 대해 내부 블록에서 선언되고 있습니다.
CREATE PROCEDURE p4 () BEGIN - outer block BEGIN - inner block DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SELECT 'SQLEXCEPTION handler was activated'AS msg; DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SELECT 'SQLSTATE handler was activated'AS msg; END; DROP TABLE test.t; - occurs within outer block END;
DROP TABLE 의 범위에 없기 때문에 두 핸들러도 적용되지 않습니다. 이 문에서 발생한 조건은 미처리되며 프로 시저를 오류로 종료시킵니다.
mysql> CALL p4();
ERROR 1051 (42S02) : Unknown table 'test.t'