Spec-Zone.ru › MySQL 5.7

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 = value, или составным оператором, написанным с использованием BEGIN и 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
      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-5.7-en/declare-handler.html

Spec-Zone.ru

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