13.6.7.4 RESIGNAL Statement语句

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 passes on the error condition information that is available during execution of a condition handler within a compound statement inside a stored procedure or function, trigger, or event. RESIGNAL传递在存储过程或函数、触发器或事件中的复合语句中执行条件处理程序期间可用的错误条件信息。RESIGNAL may change some or all information before passing it on. RESIGNAL可能会在传递信息之前更改部分或全部信息。RESIGNAL is related to SIGNAL, but instead of originating a condition as SIGNAL does, RESIGNAL relays existing condition information, possibly after modifying it.RESIGNALSIGNAL相关,但RESIGNAL并不像SIGNAL那样发出条件,而是可能在修改现有条件信息后,对其进行中继。

RESIGNAL makes it possible to both handle an error and return the error information. RESIGNAL使处理错误和返回错误信息成为可能。Otherwise, by executing an SQL statement within the handler, information that caused the handler's activation is destroyed. 否则,通过在处理程序中执行SQL语句,导致处理程序激活的信息将被销毁。RESIGNAL also can make some procedures shorter if a given handler can handle part of a situation, then pass the condition up the line to another handler.如果给定的处理程序可以处理部分情况,然后将条件“向上”传递给另一个处理程序,RESIGNAL还可以缩短一些过程。

No privileges are required to execute the RESIGNAL statement.执行RESIGNAL语句不需要任何特权。

All forms of RESIGNAL require that the current context be a condition handler. 所有形式的RESIGNAL都要求当前上下文是条件处理程序。Otherwise, RESIGNAL is illegal and a RESIGNAL when handler not active error occurs.否则,RESIGNAL是非法的,并且发生RESIGNAL when handler not active错误。

To retrieve information from the diagnostics area, use the GET DIAGNOSTICS statement (see Section 13.6.7.3, “GET DIAGNOSTICS Statement”). 要从诊断区域检索信息,请使用GET DIAGNOSTICS语句(参见第13.6.7.3节,“GET DIAGNOSTICS语句”)。For information about the diagnostics area, see Section 13.6.7.7, “The MySQL Diagnostics Area”.有关诊断区域的信息,请参阅第13.6.7.7节,“MySQL诊断区域”

RESIGNAL Overview概述

For condition_value and signal_information_item, the definitions and rules are the same for RESIGNAL as for SIGNAL. 对于condition_valuesignal_information_itemRESIGNALSIGNAL的定义和规则相同。For example, the condition_value can be an SQLSTATE value, and the value can indicate errors, warnings, or not found. 例如,condition_value可以是SQLSTATE值,该值可以指示错误、警告或“未找到”。For additional information, see Section 13.6.7.5, “SIGNAL Statement”.有关更多信息,请参阅第13.6.7.5节,“SIGNAL语句”

The RESIGNAL statement takes condition_value and SET clauses, both of which are optional. RESIGNAL语句采用condition_value子句和SET子句,这两个子句都是可选的。This leads to several possible uses:这导致了几种可能的用途:

  • RESIGNAL alone:单独:

    RESIGNAL;
  • RESIGNAL with new signal information:使用新的信号信息:

    RESIGNAL SET signal_information_item [, signal_information_item] ...;
  • RESIGNAL with a condition value and possibly new signal information:使用条件值和可能的新信号信息:

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

These use cases all cause changes to the diagnostics and condition areas:这些用例都会导致诊断和条件区域发生变化:

  • A diagnostics area contains one or more condition areas.诊断区域包含一个或多个条件区域。

  • A condition area contains condition information items, such as the SQLSTATE value, MYSQL_ERRNO, or MESSAGE_TEXT.条件区域包含条件信息项,例如SQLSTATE值、MYSQL_ERRNOMESSAGE_TEXT

There is a stack of diagnostics areas. When a handler takes control, it pushes a diagnostics area to the top of the stack, so there are two diagnostics areas during handler execution:有一堆诊断区域。当处理程序控制时,它会将诊断区域推到堆栈顶部,因此在处理程序执行期间有两个诊断区域:

  • The first (current) diagnostics area, which starts as a copy of the last diagnostics area, but is overwritten by the first statement in the handler that changes the current diagnostics area.第一个(当前)诊断区域,它以最后一个诊断区域的副本开始,但被处理程序中更改当前诊断区域的第一条语句覆盖。

  • The last (stacked) diagnostics area, which has the condition areas that were set up before the handler took control.最后一个(堆叠的)诊断区域,其中包含处理程序控制前设置的条件区域。

The maximum number of condition areas in a diagnostics area is determined by the value of the max_error_count system variable. 诊断区域中条件区域的最大数量由max_error_count系统变量的值决定。See Diagnostics Area-Related System Variables.请参阅诊断区域相关的系统变量

RESIGNAL Alone单独

A simple RESIGNAL alone means pass on the error with no change. 仅仅一个简单的RESIGNAL就意味着“不加改变地传递错误”。It restores the last diagnostics area and makes it the current diagnostics area. 它将恢复最后一个诊断区域,并使其成为当前诊断区域。That is, it pops the diagnostics area stack.也就是说,它“弹出”诊断区域堆栈。

Within a condition handler that catches a condition, one use for RESIGNAL alone is to perform some other actions, and then pass on without change the original condition information (the information that existed before entry into the handler).在捕获条件的条件处理程序中,RESIGNAL单独的一个用途是执行一些其他操作,然后在不更改原始条件信息(进入处理程序之前存在的信息)的情况下传递。

Example:例子:

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

Suppose that the DROP TABLE xx statement fails. 假设DROP TABLE xx语句失败。The diagnostics area stack looks like this:诊断区域堆栈如下所示:

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

Then execution enters the EXIT handler. 然后执行进入EXIT处理程序。It starts by pushing a diagnostics area to the top of the stack, which now looks like this:它首先将诊断区域推到堆栈顶部,现在看起来如下所示:

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

At this point, the contents of the first (current) and second (stacked) diagnostics areas are the same. 此时,第一(当前)和第二(堆叠)诊断区域的内容相同。The first diagnostics area may be modified by statements executing subsequently within the handler.第一个诊断区域可以通过随后在处理程序中执行的语句进行修改。

Usually a procedure statement clears the first diagnostics area. 通常,程序语句会清除第一个诊断区域。BEGIN is an exception, it does not clear, it does nothing. BEGIN是个例外,它不清楚,它什么也不做。SET is not an exception, it clears, performs the operation, and produces a result of success. SET不是异常,它会清除、执行操作,并产生“成功”的结果。The diagnostics area stack now looks like this:诊断区域堆栈现在如下所示:

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

At this point, if @a = 0, RESIGNAL pops the diagnostics area stack, which now looks like this:此时,如果@a=0RESIGNAL将弹出诊断区域堆栈,现在看起来如下:

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

And that is what the caller sees.这就是打电话的人看到的。

If @a is not 0, the handler simply ends, which means that there is no more use for the current diagnostics area (it has been handled), so it can be thrown away, causing the stacked diagnostics area to become the current diagnostics area again. 如果@a不是0,则处理程序将简单结束,这意味着当前诊断区域不再使用(它已被“处理”),因此可以将其丢弃,从而使堆叠的诊断区域再次成为当前诊断区域。The diagnostics area stack looks like this:诊断区域堆栈如下所示:

DA 1. ERROR 0000 (00000): Successful operation

The details make it look complex, but the end result is quite useful: Handlers can execute without destroying information about the condition that caused activation of the handler.细节让它看起来很复杂,但最终的结果非常有用:处理程序可以在不破坏导致处理程序激活的条件相关信息的情况下执行。

RESIGNAL with New Signal Information使用新的信号信息

RESIGNAL with a SET clause provides new signal information, so the statement means pass on the error with changes:RESIGNAL使用SET子句提供了新的信号信息,因此该语句的意思是“通过更改传递错误”:

RESIGNAL SET signal_information_item [, signal_information_item] ...;

As with RESIGNAL alone, the idea is to pop the diagnostics area stack so that the original information goes out. RESIGNAL一样,想法是弹出诊断区域堆栈,以便原始信息消失。Unlike RESIGNAL alone, anything specified in the SET clause changes.与单独RESIGNAL不同,SET子句中指定的任何内容都会发生更改。

Example:例子:

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

Remember from the previous discussion that RESIGNAL alone results in a diagnostics area stack like this:请记住,在前面的讨论中,RESIGNAL单独会产生如下诊断区域堆栈:

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

The RESIGNAL SET MYSQL_ERRNO = 5 statement results in this stack instead, which is what the caller sees:RESIGNAL SET MYSQL_ERRNO = 5语句将生成这个堆栈,这是调用者看到的:

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

In other words, it changes the error number, and nothing else.换句话说,它改变了错误号,其他什么都没有。

The RESIGNAL statement can change any or all of the signal information items, making the first condition area of the diagnostics area look quite different.RESIGNAL语句可以更改任何或所有信号信息项,使诊断区域的第一个条件区域看起来完全不同。

RESIGNAL with a Condition Value and Optional New Signal Information带有条件值和可选新信号信息的RESIGNAL

RESIGNAL with a condition value means push a condition into the current diagnostics area. 带有条件值的RESIGNAL表示“将条件推入当前诊断区域”。If the SET clause is present, it also changes the error information.如果存在SET子句,它还会更改错误信息。

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

This form of RESIGNAL restores the last diagnostics area and makes it the current diagnostics area. 这种形式的RESIGNAL将恢复最后一个诊断区域,并使其成为当前诊断区域。That is, it pops the diagnostics area stack, which is the same as what a simple RESIGNAL alone would do. 也就是说,它“弹出”诊断区域堆栈,这与单独RESIGNAL操作一样。However, it also changes the diagnostics area depending on the condition value or signal information.但是,它也会根据条件值或信号信息更改诊断区域。

Example:例子:

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;

This is similar to the previous example, and the effects are the same, except that if RESIGNAL happens, the current condition area looks different at the end. 这与上一个示例类似,效果相同,只是如果发生了RESIGNAL,那么当前条件区域在末尾看起来不同。(The reason the condition adds to rather than replaces the existing condition is the use of a condition value.)(条件添加到现有条件而不是替换现有条件的原因是使用了条件值。)

The RESIGNAL statement includes a condition value (SQLSTATE '45000'), so it adds a new condition area, resulting in a diagnostics area stack that looks like this:RESIGNAL语句包含一个条件值(SQLSTATE '45000'),因此它添加了一个新的条件区域,从而生成如下所示的诊断区域堆栈:

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

The result of CALL p() and SHOW ERRORS for this example is:本例的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 Requires Condition Handler Context需要条件处理程序上下文

All forms of RESIGNAL require that the current context be a condition handler. 所有形式的RESIGNAL都要求当前上下文是条件处理程序。Otherwise, RESIGNAL is illegal and a RESIGNAL when handler not active error occurs. 否则,RESIGNAL是非法的,并且发生RESIGNAL when handler not active错误。For example:例如:

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

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

Here is a more difficult example:下面是一个更难的例子:

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 occurs within the stored function f(). Although f() itself is invoked within the context of the EXIT handler, execution within f() has its own context, which is not handler context. RESIGNAL发生在存储函数f()中。虽然f()本身是在退出处理程序的上下文中调用的,但f()中的执行有自己的上下文,而不是处理程序上下文。Thus, RESIGNAL within f() results in a handler not active error.因此,f()中的RESIGNAL会导致“处理程序未激活”错误。