#### 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.html)传递在存储过程或函数、触发器或事件内的复合语句中执行条件处理程序期间可用的错误条件信息。[`重新信号`](resignal.html)可能会在传递之前更改部分或全部信息。[`重新信号`](resignal.html)与[`信号`](signal.html), 但不是将条件作为[`信号`](signal.html)做，[`重新信号`](resignal.html)中继现有的条件信息，可能在修改它之后。

[`重新信号`](resignal.html)使得处理错误和返回错误信息成为可能。否则，通过在处理程序中执行 SQL 语句，导致处理程序激活的信息被破坏。[`重新信号`](resignal.html)如果给定的处理程序可以处理部分情况，也可以缩短一些程序，然后将条件“向上”传递给另一个处理程序。

无需权限即可执行[`重新信号`](resignal.html)陈述。

所有形式的[`重新信号`](resignal.html)要求当前上下文是条件处理程序。否则，[`重新信号`](resignal.html)是非法的并且是`处理程序未激活时的 RESIGNAL`发生错误。

要从诊断区域检索信息，请使用[`获取诊断信息`](get-diagnostics.html)声明（见[第13.6.7.3节，“获取诊断声明”](get-diagnostics.html)).有关诊断区域的信息，请参阅[第13.6.7.7节，“MySQL诊断区域”](diagnostics-area.html).

-   [辞职概述](resignal.html#resignal-overview)

-   [独自辞职](resignal.html#resignal-alone)

-   [用新的信号信息辞职](resignal.html#resignal-with-new-signal)

-   [带有条件值和可选新信号信息的RESIGNAL](resignal.html#resignal-with-condition)

-   [RESIGNAL需要条件处理程序上下文](resignal.html#resignal-handler)

##### 辞职概述

对于*`条件_值`*和*`信号信息项`*，其定义和规则与[`辞职的`](resignal.html)至于[`信号`](signal.html).例如*`条件_值`*可以是一个`SQLSTATE`值，该值可以指示错误、警告或“未找到”有关更多信息，请参阅[第13.6.7.5节，“信号声明”](signal.html).

这个[`辞职的`](resignal.html)声明需要*`条件_值`*和`设置`条款，两者都是可选的。这导致了几种可能的用途：

-   [`辞职的`](resignal.html)独自一人：

    ```
    RESIGNAL;
    ```

-   [`辞职的`](resignal.html)使用新的信号信息：

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

-   [`辞职的`](resignal.html)使用条件值和可能的新信号信息：

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

    这些用例都会导致诊断和条件区域发生变化：

-   诊断区域包含一个或多个条件区域。

-   条件区域包含条件信息项，例如`SQLSTATE`价值`乌尔诺`或`短信`.

    有一堆诊断区域。当处理程序控制时，它会将诊断区域推到堆栈顶部，因此在处理程序执行期间有两个诊断区域：

-   第一个（当前）诊断区域，它以最后一个诊断区域的副本开始，但被处理程序中更改当前诊断区域的第一条语句覆盖。

-   最后一个（堆叠的）诊断区域，其中包含处理程序控制前设置的条件区域。

    诊断区域中条件区域的最大数量由[`最大错误计数`](server-system-variables.html#sysvar_max_error_count)系统变量。看见[诊断区域相关系统变量](diagnostics-area.html#diagnostics-area-system-variables).

##### 独自辞职

简单的[`辞职的`](resignal.html)孤独意味着“不加改变地传递错误”它将恢复最后一个诊断区域，并使其成为当前诊断区域。也就是说，它“弹出”诊断区域堆栈。

在捕获条件的条件处理程序中，一个用于[`辞职的`](resignal.html)单独执行一些其他操作，然后在不更改原始条件信息（进入处理程序之前存在的信息）的情况下传递。

例子：

```
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();
```

假设`放台xx`声明失败。诊断区域堆栈如下所示：

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

然后进入执行阶段`出口`汉德勒。它首先将诊断区域推到堆栈顶部，现在看起来如下所示：

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

此时，第一（当前）和第二（堆叠）诊断区域的内容相同。第一个诊断区域可以通过随后在处理程序中执行的语句进行修改。

通常，程序语句会清除第一个诊断区域。`开始`是一个例外，它不清楚，它什么也不做。`设置`不是例外，它会清除、执行操作，并产生“成功”的结果诊断区域堆栈现在如下所示：

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

在这一点上，如果`@a=0`, [`辞职的`](resignal.html)弹出diagnostics area堆栈，它现在看起来如下：

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

这就是打电话的人看到的。

如果`@a`如果不是0，则处理程序将结束，这意味着当前诊断区域不再使用（它已被“处理”），因此可以将其丢弃，从而使堆叠的诊断区域再次成为当前诊断区域。诊断区域堆栈如下所示：

```
DA 1. ERROR 0000 (00000): Successful operation
```

细节让它看起来很复杂，但最终的结果非常有用：处理程序可以在不破坏导致处理程序激活的条件相关信息的情况下执行。

##### 用新的信号信息辞职

[`辞职的`](resignal.html)用一个`设置`子句提供了新的信号信息，因此该语句表示“通过更改传递错误”：

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

就像[`辞职的`](resignal.html)单独的想法是弹出诊断区域堆栈，以便原始信息消失。不像[`辞职的`](resignal.html)仅此一项，合同中规定的任何事项`设置`条款变更。

例子：

```
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.html)单独产生的诊断区域堆栈如下所示：

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

这个`RESIGNAL SET MYSQL_ERRNO=5`语句将生成此堆栈，这是调用者看到的：

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

换句话说，它改变了错误号，其他什么都没有。

这个[`辞职的`](resignal.html)语句可以更改任何或所有信号信息项，使诊断区域的第一个条件区域看起来完全不同。

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

[`辞职的`](resignal.html)带有条件值意味着“将条件推入当前诊断区域”如果`设置`子句存在时，它还会更改错误信息。

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

这种形式的[`辞职的`](resignal.html)恢复最后一个诊断区域并使其成为当前诊断区域。也就是说，它“弹出”诊断区域堆栈，这与简单的[`辞职的`](resignal.html)一个人就行了。但是，它也会根据条件值或信号信息更改诊断区域。

例子：

```
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.html)发生这种情况时，当前条件区域在末尾看起来不同。（条件添加到现有条件而不是替换现有条件的原因是使用了条件值。）

这个[`辞职的`](resignal.html)语句包含一个条件值(`SQLSTATE'45000'`)，因此它添加了一个新的条件区域，从而生成一个诊断区域堆栈，如下所示：

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

结果[`呼叫p（）`](call.html)和[`显示错误`](show-errors.html)例如：

```
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.html)要求当前上下文是条件处理程序。否则[`辞职的`](resignal.html)是非法的`处理程序未激活时辞职`发生错误。例如：

```
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.html)在存储函数中发生`f（）`虽然`f（）`在`出口`处理程序，在`f（）`有自己的上下文，而不是处理程序上下文。因此`辞职的`在内部`f（）`导致“处理程序未激活”错误。
