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_list
NOT 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'