跳到主要内容

RESIGNAL

RESIGNAL 语句用于传递在存储过程或函数、触发器或事件内的复合语句中执行条件处理程序期间可用的错误条件信息。

RESIGNAL 的语法和参数说明

RESIGNAL 可能会在传递错误条件信息之前更改部分或全部信息。RESIGNALSIGNAL 相关,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_valuesignal_information_itemRESIGNAL 的定义和规则与 SIGNAL 相同。例如,condition_value 可以是 SQLSTATE 值,该值可以指示错误、告警或"not found"。详细信息,请参见 SIGNAL

RESIGNAL 语法中的 condition_valueSET 子句都是可选的。包括如下使用方式:

  • 单独的 RESIGNAL

    RESIGNAL;
  • 带有新信号信息的 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

以上示例说明,处理程序的执行可以不破坏导致处理程序激活的条件的有关信息。

带有新信号信息的 RESIGNAL

带有 SET 子句的 RESIGNAL 提供了新的信号信息,因此该语句的含义是"通过更改传递错误",语法如下:

RESIGNAL SET signal_information_item [, signal_information_item] ...;

与单独的 RESIGNAL 一样,通过弹出诊断区域的堆栈,从而使原始信息消失。与单独的 RESIGNAL 不同,SET 子句中指定的内容都会更改。

示例如下:

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 SET MYSQL_ERRNO = 5; 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'

RESIGNAL SET MYSQL_ERRNO = 5 语句会产生堆栈,并改变了错误号,如下所示。

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

RESIGNAL 语句可以更改任何或者所有信号信息项,使诊断区域的第一个条件区域改变了样式。

带有条件值和可选新信号信息的 RESIGNAL

带有条件值的 RESIGNAL 表示"将条件推送到当前诊断区域"。如果存在 SET 子句,它也会更改错误信息。

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

这种形式的 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 SQLSTATE '45000' SET MYSQL_ERRNO=5; END IF;
END;
DROP TABLE tbl1;
END//

delimiter ;

SET @err_count = 0;

SET @x = 0;

CALL proc();

SHOW ERRORS;

示例中,如果 RESIGNAL 发生了,当前的条件区域与之前的示例是不同的。由于使用了条件值,所以会添加条件而不是替换现有条件。

RESIGNAL 语句包含一个条件值(SQLSTATE '45000'),因此它添加了一个新的条件区域,导致诊断区域的堆栈如下所示:

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

此示例的 CALL proc()SHOW ERRORS 的结果如下:

CALL proc();
ERROR 5 (45000): Unknown table 'xx'
SHOW ERRORS;
+-------+------+----------------------------------+
| Level | Code | Message |
+-------+------+----------------------------------+
| Error | 1051 | Unknown table 'xx' |
| Error | 5 | Unknown table 'xx' |
+-------+------+----------------------------------+