13.6.7.2 ОПРЕДЕЛЕНИЕ обработчика…
DECLARE handler_action HANDLER
FOR condition_value [, condition_value] ...
statement
handler_action: {
CONTINUE
| EXIT
| UNDO
}
condition_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: Не поддерживается.
condition_value для DECLARE ...
HANDLER указывает конкретное условие или класс условий, которые активируют обработчик. Он может принимать следующие формы:
-
mysql_error_code: Целочисленная константа, указывающая код ошибки MySQL, например, 1051 для указания «“неизвестная таблица”»:DECLARE CONTINUE HANDLER FOR 1051 BEGIN -- body of handler END;Не используйте код ошибки MySQL 0, поскольку он указывает на успех, а не на условие ошибки. Список кодов ошибок MySQL см. в .
-
SQLSTATE [VALUE]
sqlstate_value: Строковая константа длиной 5 символов, указывающая значение SQLSTATE, например,'42S01'для указания «“неизвестная таблица”»:DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' BEGIN -- body of handler END;Не используйте значения SQLSTATE, начинающиеся с
'00', поскольку они указывают на успех, а не на условие ошибки. Список значений SQLSTATE см. в . condition_name: Имя условия, ранее указанное с помощьюDECLARE ... CONDITION. Имя условия может быть связано с кодом ошибки MySQL или значением SQLSTATE. См. Раздел 13.6.7.1, «Оператор DECLARE ... CONDITION».-
SQLWARNING: Сокращение для класса значений SQLSTATE, начинающихся с'01'.DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN -- body of handler END; -
NOT FOUND: Сокращение для класса значений SQLSTATE, начинающихся с'02'. Это актуально в контексте курсоров и используется для управления тем, что происходит, когда курсор достигает конца набора данных. Если больше строк недоступно, возникает условие «Нет данных» со значением SQLSTATE'02000'. Чтобы обнаружить это условие, можно настроить обработчик для него или для условияNOT FOUND.DECLARE CONTINUE HANDLER FOR NOT FOUND BEGIN -- body of handler END;Для другого примера см. Раздел 13.6.6, «Курсоры». Условие
NOT FOUNDтакже возникает для операторовSELECT ... INTO, которые не извлекают строк.var_list -
SQLEXCEPTION: Сокращение для класса значений SQLSTATE, которые не начинаются с'00','01'или'02'.DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN -- body of handler END;
Информация о том, как сервер выбирает обработчики при возникновении условия, содержится в Разделе 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 не был присутствовать, MySQL выполнил бы действие по умолчанию (EXIT) после того, как второе выполнение оператора INSERT завершилось неудачно из-за ограничения PRIMARY KEY, и 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 BEGINblock 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;
© 2025 Oracle
Licensed under the GPLv2 License.