RESIGNAL
RESIGNAL 语句用于传递在存储过程或函数、触发器或事件内的复合语句中执行条件处理程序期间可用的错误条件信息。
RESIGNAL 的语法和参数说明
RESIGNAL 可能会在传递错误条件信息之前更改部分或全部信息。RESIGNAL 与 SIGNAL 相关,SIGNAL 可以发起条件,而 RESIGNAL 只能基于现有错误信息来进行对应修改。
执行 RESIGNAL 语句不需要任何权限。
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: {
MESSAGE_TEXT
| MYSQL_ERRNO
}
对于 condition_value 和 signal_information_item,RESIGNAL 的定义和规则与 SIGNAL 相同。例如,condition_value 可以是 SQLSTATE 值,该值可以指示错误、告警或"not found"。详细信息,请参见 SIGNAL。
RESIGNAL 语法中的 condition_value 和 SET 子句都是可 选的。包括如下使用方式:
-
单独的
RESIGNALRESIGNAL; -
带有新信号信息的
RESIGNAL:RESIGNAL SET signal_information_item [, signal_information_item] ...; -
带有条件值和可能的新信号信息的
RESIGNAL:RESIGNAL condition_value
[SET signal_information_item [, signal_information_item] ...];
以上用法都会导致诊断和条件区域发生如下变化:
-
一个诊断区域包含一个或多个条件区域。
-
条件区域包含条件信息项,例如
SQLSTATE值或MESSAGE_TEXT。
对于堆栈的诊断区域,当处理程序获得控制权时,它会将诊断区域推送到堆栈顶部,因此处理程序执行期间有两个诊断区域:
-
第一个(当前)诊断区域,也是最后一个诊断区域的副本作为开始,会被处理程序更改当前诊断区域的第一条语句覆盖。
-
最后一个(堆栈的)诊断区域,包含在处理程序开始控制之前所设置的条件区域。
诊断区域中条件区域的最大数量由 max_error_count 系统变量的值确定。
所有形式的 RESIGNAL 都要求当前上下文是条件处理程序。否则,RESIGNAL 是非法的,并且当处理程序不活动时会发生报错。示例如下:
CREATE PROCEDURE p1() RESIGNAL;
Query OK, 0 rows affected
CALL p1();
ERROR 1645 (0K000): RESIGNAL when handler not active
单独的 RESIGNAL
一个简单的 RESIGNAL 的含义是"不做任何更改地传递错误",仅使用 RESIGNAL 可以用于恢复上一个诊断区域并使其成为当前诊断区域。也就是说,它会"弹出"诊断区域的堆栈。
示例如下:
DROP TABLE IF EXISTS tbl1;
delimiter //
CREATE PROCEDURE proc()
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SET @err_count = @err_count + 1;
IF @x = 0 THEN RESIGNAL; END IF;
END;
DROP TABLE tbl1;
END//
delimiter ;
SET @err_count = 0;
SET @x = 0;
CALL proc();
假设 DROP TABLE tbl1 语句执行失败。诊断区域堆栈如下所示:
DA 1. ERROR 1051 (42S02): Unknown table 'tbl1'
然后执行进入 EXIT 处理程序。它首先将诊断区域推送到堆栈顶部,如下所示:
DA 1. ERROR 1051 (42S02): Unknown table 'tbl1'
DA 2. ERROR 1051 (42S02): Unknown table 'tbl1'
此时,第一(当前)和第二(堆栈)诊断区域的内容是相同的,之后可以通过在处理程序中执行的语句来修改第一诊断区域。
通常一个过程语句会清除第一个诊断区域(BEGIN 除外)。而 SET 语句可以清除、执行操作并产生"成功"的结果。现在的诊断区域堆栈如下所示:
DA 1. ERROR 0000 (00000): Successful operation
DA 2. ERROR 1051 (42S02): Unknown table 'tbl1'
此时,如果 @x = 0,则 RESIGNAL 会弹出诊断区域的堆栈,现在的诊断区如下所示:
DA 1. ERROR 1051 (42S02): Unknown table 'tbl1'
如果 @x 不为 0,则处理程序就会结束,这意味着当前的诊断区域没有更多用处(它已被"处理"),因此可以将其丢弃,导致堆栈的诊断区域再次成为当前的诊断区域。当前的诊断区域堆栈如下所示:
DA 1. ERROR 0000 (00000): Successful operation
以上示例说明,处理程序的执行可以不破坏导致处理程序激活的条件的有关信息。