15.6.7.2 Оператор DECLARE ... HANDLER
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 (см. Раздел 15.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. См. Раздел 15.6.7.1, «DECLARE ... CONDITION Оператор».-
SQLWARNING: Сокращение для класса значений SQLSTATE, начинающихся с'01'.DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN -- body of handler END; -
NOT FOUND: Сокращение для класса значений SQLSTATE, начинающихся с'02'. Это актуально в контексте курсоров и используется для управления тем, что происходит, когда курсор достигает конца набора данных. Если больше нет строк, возникает условие No Data со значением SQLSTATE'02000'. Чтобы обнаружить это условие, вы можете настроить обработчик для него или для условияNOT FOUND.DECLARE CONTINUE HANDLER FOR NOT FOUND BEGIN -- body of handler END;Для другого примера см. Раздел 15.6.6, «Курсоры». Условие
NOT FOUNDтакже возникает для операторовSELECT ... INTO, которые не извлекают строк.var_list -
SQLEXCEPTION: Сокращение для класса значений SQLSTATE, которые не начинаются с'00','01'или'02'.DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN -- body of handler END;
Информацию о том, как сервер выбирает обработчики при возникновении условия, см. в Разделе 15.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.