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
相關,但 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 診斷區域」。
對於 condition_value
和 signal_information_item
,RESIGNAL
的定義和規則與 SIGNAL
相同。例如,condition_value
可以是 SQLSTATE
值,而且該值可以指出錯誤、警告或「找不到。」。如需其他資訊,請參閱 第 15.6.7.5 節「SIGNAL 陳述式」。
RESIGNAL
陳述式會採用 condition_value
和 SET
子句,這兩者都是選用的。這會導致幾種可能的使用方式
這些使用案例都會導致診斷和條件區域發生變更
診斷區域包含一或多個條件區域。
條件區域包含條件資訊項目,例如
SQLSTATE
值、MYSQL_ERRNO
或MESSAGE_TEXT
。
診斷區域會堆疊。當處理常式取得控制時,它會將診斷區域推送到堆疊頂端,因此在處理常式執行期間會有兩個診斷區域
第一個 (目前的) 診斷區域,一開始是最後一個診斷區域的複本,但會被處理常式中第一個變更目前診斷區域的陳述式覆寫。
最後一個 (堆疊的) 診斷區域,其具有在處理常式取得控制之前設定的條件區域。
診斷區域中條件區域的最大數目是由 max_error_count
系統變數的值所決定。請參閱診斷區域相關的系統變數。
單獨使用簡單的 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 = 0
,RESIGNAL
會彈出診斷區域堆疊,現在看起來像這樣
DA 1. ERROR 1051 (42S02): Unknown table 'xx'
這就是呼叫者看到的。
如果 @a
不為 0,則處理常式只會結束,這表示不再需要目前的診斷區域 (它已「處理」),因此可以捨棄,導致堆疊的診斷區域再次成為目前的診斷區域。診斷區域堆疊看起來像這樣
DA 1. ERROR 0000 (00000): Successful operation
詳細資訊讓它看起來很複雜,但最終結果相當有用:處理常式可以執行,而不會破壞導致處理常式啟動的條件的相關資訊。
搭配 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
表示「將條件推入目前的診斷區域。」如果存在 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 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」 錯誤。