Spec-Zone.ru › MySQL 8.4

15.6.7.4 Оператор RESIGNAL

RESIGNAL [condition_value]
    [SET signal_information_item
    [, signal_information_item] ...]

condition_value: {
    SQLSTATE [VALUE] sqlstate_value
  | condition_name
}

signal_information_item:
    condition_information_item_name = simple_value_specification

condition_information_item_name: {
    CLASS_ORIGIN
  | SUBCLASS_ORIGIN
  | MESSAGE_TEXT
  | MYSQL_ERRNO
  | CONSTRAINT_CATALOG
  | CONSTRAINT_SCHEMA
  | CONSTRAINT_NAME
  | CATALOG_NAME
  | SCHEMA_NAME
  | TABLE_NAME
  | COLUMN_NAME
  | CURSOR_NAME
}

condition_name, simple_value_specification:
    (see following discussion)

RESIGNAL передает информацию об ошибке, доступную во время выполнения обработчика условия в составном операторе внутри хранимой процедуры или функции, триггера или события. RESIGNAL может изменить часть или всю информацию перед передачей. RESIGNAL связан с SIGNAL, но вместо создания условия, как делает SIGNAL, RESIGNAL передает существующую информацию об условии, возможно после её изменения.

RESIGNAL позволяет как обработать ошибку, так и вернуть информацию об ошибке. В противном случае, выполняя оператор SQL внутри обработчика, информация, вызвавшая активацию обработчика, будет уничтожена. RESIGNAL также может сократить некоторые процедуры, если данный обработчик может обработать часть ситуации, а затем передать условие «вверх по цепочке» другому обработчику.

Для выполнения оператора RESIGNAL привилегии не требуются.

Все формы оператора RESIGNAL требуют, чтобы текущий контекст был обработчиком условия. В противном случае, RESIGNAL является недопустимым и возникает ошибка RESIGNAL when handler not active.

Для извлечения информации из области диагностики используйте оператор GET DIAGNOSTICS (см. Раздел 15.6.7.3, «Оператор GET DIAGNOSTICS»). Информацию об области диагностики см. в Разделе 15.6.7.7, «Область диагностики MySQL».

  • Обзор RESIGNAL

  • RESIGNAL без параметров

  • RESIGNAL с новой информацией о сигнале

  • RESIGNAL со значением условия и необязательной новой информацией о сигнале

  • Оператор RESIGNAL требует контекста обработчика условия

Обзор RESIGNAL

Для condition_value и signal_information_item, определения и правила для оператора RESIGNAL такие же, как и для SIGNAL. Например, condition_value может быть значением SQLSTATE, и это значение может указывать на ошибки, предупреждения или “не найдено.” Дополнительную информацию см. в Разделе 15.6.7.5, «Оператор SIGNAL».

Оператор RESIGNAL принимает condition_value и SET предложения, оба из которых необязательны. Это приводит к нескольким возможным вариантам использования:

  • RESIGNAL сам по себе:

    RESIGNAL;
    
  • RESIGNAL с новой информацией о сигнале:

    RESIGNAL SET signal_information_item [, signal_information_item] ...;
    
  • RESIGNAL со значением условия и, возможно, новой информацией о сигнале:

    RESIGNAL condition_value
        [SET signal_information_item [, signal_information_item] ...];
    

Все эти варианты использования приводят к изменениям в областях диагностики и условий:

  • Область диагностики содержит одну или несколько областей условий.

  • Область условия содержит элементы информации об условии, такие как значение SQLSTATE, MYSQL_ERRNO или MESSAGE_TEXT.

Существует стек областей диагностики. Когда обработчик получает управление, он помещает область диагностики на вершину стека, поэтому во время выполнения обработчика есть две области диагностики:

  • Первая (текущая) область диагностики, которая начинается как копия последней области диагностики, но перезаписывается первым оператором в обработчике, изменяющим текущую область диагностики.

  • Последняя (находящаяся в стеке) область диагностики, которая содержит области условий, установленные до того, как обработчик получил управление.

Максимальное количество областей условий в области диагностики определяется значением системной переменной max_error_count. См. Системные переменные, связанные с областью диагностики.

RESIGNAL без параметров

Простой оператор RESIGNAL без параметров означает “передать ошибку без изменений”. Он восстанавливает последнюю область диагностики и делает её текущей областью диагностики. То есть, он «извлекает» область диагностики из стека.

Внутри обработчика условия, который ловит условие, одно из применений оператора RESIGNAL без параметров заключается в выполнении других действий, а затем передаче без изменений исходной информации об условии (информации, существовавшей до входа в обработчик).

Пример:

DROP TABLE IF EXISTS xx;
delimiter //
CREATE PROCEDURE p ()
BEGIN
  DECLARE EXIT HANDLER FOR SQLEXCEPTION
  BEGIN
    SET @error_count = @error_count + 1;
    IF @a = 0 THEN RESIGNAL; END IF;
  END;
  DROP TABLE xx;
END//
delimiter ;
SET @error_count = 0;
SET @a = 0;
CALL p();

Предположим, что оператор DROP TABLE xx не выполняется успешно. Стек областей диагностики выглядит так:

DA 1. ERROR 1051 (42S02): Unknown table 'xx'

Затем выполнение входит в обработчик EXIT. Он начинает с помещения области диагностики на вершину стека, который теперь выглядит так:

DA 1. ERROR 1051 (42S02): Unknown table 'xx'
DA 2. ERROR 1051 (42S02): Unknown table 'xx'

В этот момент содержимое первой (текущей) и второй (находящейся в стеке) областей диагностики одинаковы. Первая область диагностики может быть изменена операторами, которые выполняются после этого в рамках обработчика.

Обычно оператор процедуры очищает первую область диагностики. Оператор BEGIN является исключением; он не очищает, а ничего не делает. Оператор SET не является исключением; он очищает, выполняет операцию и возвращает результат «успешно». Стек областей диагностики теперь выглядит так:

DA 1. ERROR 0000 (00000): Successful operation
DA 2. ERROR 1051 (42S02): Unknown table 'xx'

В этот момент, если @a = 0, оператор RESIGNAL извлекает область диагностики из стека, который теперь выглядит так:

DA 1. ERROR 1051 (42S02): Unknown table 'xx'

И именно это видит вызывающая сторона.

Если @a не равно 0, обработчик просто заканчивает работу, а это означает, что текущая область диагностики больше не нужна (она была «обработана»), поэтому её можно отбросить, что приводит к тому, что область диагностики в стеке становится текущей областью диагностики снова. Стек областей диагностики выглядит так:

DA 1. ERROR 0000 (00000): Successful operation

Детали выглядят сложно, но конечный результат весьма полезен: обработчики могут выполняться без уничтожения информации об условии, которое вызвало активацию обработчика.

RESIGNAL с новой информацией о сигнале

RESIGNAL с предложением SET предоставляет новую информацию о сигнале, поэтому оператор означает “передать ошибку с изменениями”:

RESIGNAL SET signal_information_item [, signal_information_item] ...;

Как и в случае с оператором RESIGNAL без параметров, идея состоит в том, чтобы извлечь область диагностики из стека, чтобы исходная информация была передана. В отличие от оператора RESIGNAL без параметров, всё, что указано в предложении SET, изменяется.

Пример:

DROP TABLE IF EXISTS xx;
delimiter //
CREATE PROCEDURE p ()
BEGIN
  DECLARE EXIT HANDLER FOR SQLEXCEPTION
  BEGIN
    SET @error_count = @error_count + 1;
    IF @a = 0 THEN RESIGNAL SET MYSQL_ERRNO = 5; END IF;
  END;
  DROP TABLE xx;
END//
delimiter ;
SET @error_count = 0;
SET @a = 0;
CALL p();

Помните из предыдущего обсуждения, что оператор RESIGNAL без параметров приводит к стеку областей диагностики, такому как:

DA 1. ERROR 1051 (42S02): Unknown table 'xx'

Оператор RESIGNAL SET MYSQL_ERRNO = 5 приводит к этому стеку вместо этого, что видит вызывающая сторона:

DA 1. ERROR 5 (42S02): Unknown table 'xx'

Другими словами, он меняет номер ошибки, и ничего больше.

Оператор RESIGNAL может изменить любой или все элементы информации о сигнале, делая первую область условия в области диагностики совершенно другой.

Операция RESIGNAL с значением условия и необязательной новой информацией о сигнале

RESIGNAL со значением условия означает “добавить условие в текущую область диагностики.” Если присутствует фрагмент SET, то также изменяется информация об ошибке.

RESIGNAL condition_value
    [SET signal_information_item [, signal_information_item] ...];

Этот вариант оператора RESIGNAL восстанавливает последнюю область диагностики и делает её текущей. То есть, он “извлекает” область диагностики из стека, что аналогично простому оператору RESIGNAL. Однако он также изменяет область диагностики в зависимости от значения условия или информации о сигнале.

Пример:

DROP TABLE IF EXISTS xx;
delimiter //
CREATE PROCEDURE p ()
BEGIN
  DECLARE EXIT HANDLER FOR SQLEXCEPTION
  BEGIN
    SET @error_count = @error_count + 1;
    IF @a = 0 THEN RESIGNAL SQLSTATE '45000' SET MYSQL_ERRNO=5; END IF;
  END;
  DROP TABLE xx;
END//
delimiter ;
SET @error_count = 0;
SET @a = 0;
SET @@max_error_count = 2;
CALL p();
SHOW ERRORS;

Это похоже на предыдущий пример, и эффекты те же, за исключением того, что если RESIGNAL произойдет, текущая область условий будет выглядеть по-другому в конце. (Причина, по которой условие добавляется, а не заменяет существующее условие, заключается в использовании значения условия.)

Оператор RESIGNAL включает значение условия (SQLSTATE '45000'), поэтому он добавляет новую область условий, что приводит к стеку областей диагностики, который выглядит так:

DA 1. (condition 2) ERROR 1051 (42S02): Unknown table 'xx'
      (condition 1) ERROR 5 (45000) Unknown table 'xx'

Результат выполнения CALL p() и SHOW ERRORS в этом примере:

mysql> CALL p();
ERROR 5 (45000): Unknown table 'xx'
mysql> SHOW ERRORS;
+-------+------+----------------------------------+
| Level | Code | Message                          |
+-------+------+----------------------------------+
| Error | 1051 | Unknown table 'xx'               |
| Error |    5 | Unknown table 'xx'               |
+-------+------+----------------------------------+
Операция RESIGNAL требует контекста обработчика условий

Все формы оператора RESIGNAL требуют, чтобы текущий контекст был контекстом обработчика условий. В противном случае RESIGNAL является недопустимым и возникает ошибка RESIGNAL when handler not active. Например:

mysql> CREATE PROCEDURE p () RESIGNAL;
Query OK, 0 rows affected (0.00 sec)

mysql> CALL p();
ERROR 1645 (0K000): RESIGNAL when handler not active

Вот более сложный пример:

delimiter //
CREATE FUNCTION f () RETURNS INT
BEGIN
  RESIGNAL;
  RETURN 5;
END//
CREATE PROCEDURE p ()
BEGIN
  DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @a=f();
  SIGNAL SQLSTATE '55555';
END//
delimiter ;
CALL p();

Оператор RESIGNAL находится внутри сохранённой функции f(). Хотя сама функция f() вызывается в контексте обработчика EXIT, выполнение внутри f() имеет свой собственный контекст, который не является контекстом обработчика. Таким образом, оператор RESIGNAL внутри f() приводит к ошибке “обработчик не активен”.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-8.4-en/resignal.html

Spec-Zone.ru

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