Documentation Home

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发起条件,而是中继现有条件信息,可能在修改它之后。 SIGNALRESIGNAL

RESIGNAL使得处理错误和返回错误信息成为可能。否则,通过在处理程序中执行 SQL 语句,导致处理程序激活的信息将被销毁。 RESIGNAL如果给定的处理程序可以处理部分情况,则还可以缩短一些过程,然后将条件向上传递给另一个处理程序。

RESIGNAL执行语句 不需要特权 。

所有形式的RESIGNAL都要求当前上下文是一个条件处理程序。否则, RESIGNAL是非法的, RESIGNAL when handler not active会发生错误。

要从诊断区域检索信息,请使用 GET DIAGNOSTICS语句(请参阅 第 13.6.7.3 节,“GET DIAGNOSTICS 语句”)。有关诊断区域的信息,请参阅第 13.6.7.7 节,“MySQL 诊断区域”

信号概述

对于condition_valuesignal_information_item,定义和规则与 for RESIGNAL相同 SIGNAL。例如, condition_value可以是一个 SQLSTATE值,该值可以指示错误、警告或未找到”。有关其他信息,请参阅第 13.6.7.5 节,“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] ...];

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.

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. See Diagnostics Area-Related System Variables.

RESIGNAL Alone

A simple RESIGNAL alone means pass on the error with no change. 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).

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. The diagnostics area stack looks like this:

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

Then execution enters the EXIT handler. 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. SET is not an exception, it clears, performs the operation, and produces a result of success. 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:

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. 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 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. Unlike RESIGNAL alone, anything specified in the SET clause changes.

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:

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:

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 with a Condition Value and Optional New Signal Information

RESIGNAL with a condition value means push a condition into the current diagnostics area. If the SET clause is present, it also changes the error information.

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. That is, it pops the diagnostics area stack, which is the same as what a simple RESIGNAL alone would do. 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. (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:

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:

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. Otherwise, RESIGNAL is illegal and a RESIGNAL when handler not active error occurs. 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发生在存储函数f()中。虽然 f()它本身是在处理程序的上下文中调用的,但是其中的EXIT执行 f()有它自己的上下文,而不是处理程序上下文。因此,RESIGNALwithin f()会导致处理程序未激活错误。