DECLARE handler_action HANDLER
FOR condition_value [, condition_value] ...
statement
handler_action: {
CONTINUE
| EXIT
| UNDO
}
condition_value: {
mysql_error_code
| SQLSTATE [VALUE] sqlstate_value
| condition_name
| SQLWARNING
| NOT FOUND
| SQLEXCEPTION
}
DECLARE ... HANDLER
陳述式會指定一個處理器,用來處理一個或多個條件。如果這些條件之一發生,則會執行指定的 statement
。statement
可以是簡單的陳述式,例如 SET
,或是使用 var_name
= value
BEGIN
和 END
編寫的複合陳述式(請參閱第 15.6.1 節「BEGIN ... END 複合陳述式」)。
處理器宣告必須出現在變數或條件宣告之後。
handler_action
值表示處理器在執行處理器陳述式後所採取的動作。
CONTINUE
:繼續執行目前的程式。EXIT
:終止宣告處理器的BEGIN ... END
複合陳述式的執行。即使條件發生在內部區塊中,也是如此。UNDO
:不支援。
DECLARE ... HANDLER
的 condition_value
表示會啟動處理器的特定條件或條件類別。它可以採用以下形式:
mysql_error_code
:一個整數常值,表示 MySQL 錯誤代碼,例如 1051 表示「未知資料表」。DECLARE CONTINUE HANDLER FOR 1051 BEGIN -- body of handler END;
請勿使用 MySQL 錯誤代碼 0,因為這表示成功,而不是錯誤狀況。如需 MySQL 錯誤代碼的清單,請參閱伺服器錯誤訊息參考。
SQLSTATE [VALUE]
sqlstate_value
:一個 5 個字元的字串常值,表示 SQLSTATE 值,例如'42S01'
表示「未知資料表」。DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' BEGIN -- body of handler END;
請勿使用以
'00'
開頭的 SQLSTATE 值,因為這些值表示成功,而不是錯誤狀況。如需 SQLSTATE 值的清單,請參閱伺服器錯誤訊息參考。condition_name
:先前使用DECLARE ... CONDITION
指定的條件名稱。條件名稱可以與 MySQL 錯誤代碼或 SQLSTATE 值相關聯。請參閱第 15.6.7.1 節「DECLARE ... CONDITION 陳述式」。SQLWARNING
:以'01'
開頭的 SQLSTATE 值類別的簡寫。DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN -- body of handler END;
NOT FOUND
:以'02'
開頭的 SQLSTATE 值類別的簡寫。這與游標的內容相關,並用於控制游標到達資料集結尾時會發生的情況。如果沒有更多列可用,則會發生 SQLSTATE 值為'02000'
的「無資料」條件。若要偵測此條件,您可以為此條件或NOT FOUND
條件設定處理器。DECLARE CONTINUE HANDLER FOR NOT FOUND BEGIN -- body of handler END;
如需其他範例,請參閱第 15.6.6 節「游標」。
NOT FOUND
條件也會發生在未擷取任何列的SELECT ... INTO
陳述式中。var_list
SQLEXCEPTION
:不以'00'
、'01'
或'02'
開頭的 SQLSTATE 值類別的簡寫。DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN -- body of handler END;
如需伺服器在條件發生時如何選擇處理器的資訊,請參閱第 15.6.7.6 節「處理器的範圍規則」。
如果發生未宣告任何處理器的條件,則採取的動作取決於條件類別。
下列範例使用 SQLSTATE '23000'
的處理器,這會在重複鍵錯誤時發生。
mysql> CREATE TABLE test.t (s1 INT, PRIMARY KEY (s1));
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter //
mysql> CREATE PROCEDURE handlerdemo ()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;
SET @x = 1;
INSERT INTO test.t VALUES (1);
SET @x = 2;
INSERT INTO test.t VALUES (1);
SET @x = 3;
END;
//
Query OK, 0 rows affected (0.00 sec)
mysql> CALL handlerdemo()//
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @x//
+------+
| @x |
+------+
| 3 |
+------+
1 row in set (0.00 sec)
請注意,程序執行後 @x
為 3
,這表示在發生錯誤後,執行繼續到程序結尾。如果 DECLARE ... HANDLER
陳述式不存在,則在第二個 INSERT
因 PRIMARY KEY
限制而失敗後,MySQL 會採取預設動作 (EXIT
),並且 SELECT @x
會傳回 2
。
若要忽略條件,請為其宣告 CONTINUE
處理器,並將其與空的區塊建立關聯。例如:
DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN END;
區塊標籤的範圍不包含在區塊中宣告的處理器的程式碼。因此,與處理器相關聯的陳述式無法使用 ITERATE
或 LEAVE
來參考封閉處理器宣告的區塊的標籤。請考慮下列範例,其中 REPEAT
區塊的標籤為 retry
。
CREATE PROCEDURE p ()
BEGIN
DECLARE i INT DEFAULT 3;
retry:
REPEAT
BEGIN
DECLARE CONTINUE HANDLER FOR SQLWARNING
BEGIN
ITERATE retry; # illegal
END;
IF i < 0 THEN
LEAVE retry; # legal
END IF;
SET i = i - 1;
END;
UNTIL FALSE END REPEAT;
END;
retry
標籤在區塊中 IF
陳述式的範圍內。它不在 CONTINUE
處理器的範圍內,因此該處的參考無效,並會導致錯誤。
ERROR 1308 (42000): LEAVE with no matching label: retry
若要避免在處理器中參考外部標籤,請使用下列其中一種策略:
若要離開區塊,請使用
EXIT
處理器。如果不需要區塊清除,則BEGIN ... END
處理器主體可以是空的。DECLARE EXIT HANDLER FOR SQLWARNING BEGIN END;
否則,請將清除陳述式放在處理器主體中。
DECLARE EXIT HANDLER FOR SQLWARNING BEGIN block cleanup statements END;
若要繼續執行,請在
CONTINUE
處理器中設定狀態變數,此變數可在封閉區塊中檢查,以判斷是否已叫用處理器。下列範例使用變數done
來達到此目的。CREATE PROCEDURE p () BEGIN DECLARE i INT DEFAULT 3; DECLARE done INT DEFAULT FALSE; retry: REPEAT BEGIN DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN SET done = TRUE; END; IF done OR i < 0 THEN LEAVE retry; END IF; SET i = i - 1; END; UNTIL FALSE END REPEAT; END;