文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 40.0Mb
PDF (A4) - 40.1Mb
手冊頁 (TGZ) - 258.2Kb
手冊頁 (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 參考手冊  /  ...  /  RESIGNAL 陳述式

15.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 可以在傳遞資訊之前變更部分或所有資訊。RESIGNALSIGNAL 相關,但 RESIGNAL 並非如 SIGNAL 一樣產生條件,而是轉送現有的條件資訊,可能在修改後進行轉送。

RESIGNAL 可以處理錯誤並傳回錯誤資訊。否則,在處理常式中執行 SQL 陳述式會破壞導致處理常式啟動的資訊。RESIGNAL 如果給定的處理常式可以處理部分情況,然後將條件向上傳遞到另一個處理常式,也可以縮短某些程序。

執行 RESIGNAL 陳述式不需要任何權限。

RESIGNAL 的所有形式都要求目前的內容必須是條件處理常式。否則,RESIGNAL 是非法的,並會發生 RESIGNAL when handler not active 錯誤。

若要從診斷區域擷取資訊,請使用 GET DIAGNOSTICS 陳述式 (請參閱 第 15.6.7.3 節「GET DIAGNOSTICS 陳述式」)。如需診斷區域的相關資訊,請參閱 第 15.6.7.7 節「MySQL 診斷區域」

RESIGNAL 概觀

對於 condition_valuesignal_information_itemRESIGNAL 的定義和規則與 SIGNAL 相同。例如,condition_value 可以是 SQLSTATE 值,而且該值可以指出錯誤、警告或找不到。。如需其他資訊,請參閱 第 15.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] ...];

這些使用案例都會導致診斷和條件區域發生變更

  • 診斷區域包含一或多個條件區域。

  • 條件區域包含條件資訊項目,例如 SQLSTATE 值、MYSQL_ERRNOMESSAGE_TEXT

診斷區域會堆疊。當處理常式取得控制時,它會將診斷區域推送到堆疊頂端,因此在處理常式執行期間會有兩個診斷區域

  • 第一個 (目前的) 診斷區域,一開始是最後一個診斷區域的複本,但會被處理常式中第一個變更目前診斷區域的陳述式覆寫。

  • 最後一個 (堆疊的) 診斷區域,其具有在處理常式取得控制之前設定的條件區域。

診斷區域中條件區域的最大數目是由 max_error_count 系統變數的值所決定。請參閱診斷區域相關的系統變數

單獨使用 RESIGNAL

單獨使用簡單的 RESIGNAL 表示傳遞錯誤,且不進行任何變更。它會還原最後一個診斷區域,並使其成為目前的診斷區域。也就是說,它會彈出診斷區域堆疊。

在捕捉到條件的條件處理常式中,單獨使用 RESIGNAL 的一種用途是執行一些其他動作,然後傳遞未變更的原始條件資訊 (在進入處理常式之前存在的資訊)。

範例

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

假設 DROP TABLE xx 陳述式失敗。診斷區域堆疊看起來像這樣

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

接著執行進入 EXIT 處理常式。它會先將診斷區域推送到堆疊頂端,現在看起來像這樣

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

此時,第一個 (目前的) 和第二個 (堆疊的) 診斷區域的內容相同。第一個診斷區域可能會被後續在處理常式中執行的陳述式修改。

通常,程序陳述式會清除第一個診斷區域。BEGIN 是一個例外,它不會清除,它什麼都不做。SET 不是例外,它會清除、執行作業,並產生成功的結果。診斷區域堆疊現在看起來像這樣

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

此時,如果 @a = 0RESIGNAL 會彈出診斷區域堆疊,現在看起來像這樣

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

這就是呼叫者看到的。

如果 @a 不為 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 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 會產生像這樣的診斷區域堆疊

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

RESIGNAL SET MYSQL_ERRNO = 5 陳述式會產生此堆疊,這就是呼叫者看到的

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

換句話說,它會變更錯誤號碼,且不會變更其他任何項目。

RESIGNAL 陳述式可以變更任何或所有訊號資訊項目,使得診斷區域的第一個條件區域看起來非常不同。

搭配條件值和選用的新訊號資訊使用 RESIGNAL

搭配條件值使用 RESIGNAL 表示將條件推入目前的診斷區域。如果存在 SET 子句,它也會變更錯誤資訊。

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

此形式的 RESIGNAL 會還原最後一個診斷區域,並使其成為目前的診斷區域。也就是說,它會彈出診斷區域堆疊,這與單獨使用簡單的 RESIGNAL 會執行的操作相同。不過,它也會根據條件值或訊號資訊來變更診斷區域。

範例

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,則目前的條件區域在結尾處看起來會不同。(條件新增至而非取代現有條件的原因是使用條件值。)

RESIGNAL 陳述式包含條件值 (SQLSTATE '45000'),因此它會新增一個新的條件區域,導致診斷區域堆疊看起來像這樣

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

此範例中,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 需要條件處理常式環境

RESIGNAL 的所有形式都要求目前環境為條件處理常式。否則,RESIGNAL 將會是非法的,並會發生 RESIGNAL when handler not active 錯誤。例如:

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 發生在儲存函數 f() 內。儘管 f() 本身是在 EXIT 處理常式的環境中呼叫的,但 f() 內的執行有其自己的環境,而不是處理常式環境。因此,f() 內的 RESIGNAL 會導致 handler not active 錯誤。