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 = valueBEGIN 和 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_listSQLEXCEPTION:不以'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;