13.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 (см. Раздел 13.6.7.3, «Оператор GET DIAGNOSTICS»). Для получения информации об области диагностики см. Раздел 13.6.7.7, «Область диагностики MySQL».
Обзор оператора RESIGNAL
Для condition_value и signal_information_item, определения и правила такие же для RESIGNAL, как и для SIGNAL. Например, condition_value может быть значением SQLSTATE, и это значение может указывать на ошибки, предупреждения или “не найдено.” Дополнительную информацию см. в разделе 13.6.7.5, «Оператор SIGNAL».
Оператор RESIGNAL принимает condition_value и SET-клаузы, которые являются необязательными. Это приводит к нескольким возможным вариантам использования:
-
RESIGNALбез параметров:RESIGNAL;
-
RESIGNALс новой информацией о сигнале:RESIGNAL SET
signal_information_item[,signal_information_item] ...; -
RESIGNALсо значением условия и, возможно, новой информацией о сигнале:RESIGNAL
condition_value[SETsignal_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 со значением условия означает “поместить условие в текущую область диагностики.” Если присутствует фраза 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 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.