Spec-Zone.ru › MySQL 9.2

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 = value, или составным оператором, записанным с использованием BEGIN и 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
      BEGIN
        block cleanup statements
      END;
    
  • Для продолжения выполнения установите переменную состояния в обработчике 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.
https://docs.oracle.com/cd/E17952_01/mysql-8.4-en/declare-handler.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API