DECLARE handler_type HANDLER FOR condition_value[, ...] statement;
handler_type: CONTINUE | EXIT | UNDO(暫不支援)
condition_value:
SQLSTATE [VALUE] sqlstate_value
| condition_name
| SQLWARNING
| NOT FOUND
| SQLEXCEPTION
| mysql_error_code
| 類別 | 代表 | 適用場景 |
|---|---|---|
SQLSTATE '23000' | 完整性約束違反(重複鍵、FK 失效) | 精確捕獲特定錯誤 |
1062 | Duplicate entry (MySQL 錯誤碼) | 等同 23000,更直觀 |
SQLWARNING | 所有 01 開頭的 SQLSTATE | 捕獲警告(如截斷、預設值) |
NOT FOUND | 所有 02 開頭的 SQLSTATE + 游標結束 | 游標迴圈結束控制 |
SQLEXCEPTION | 除上述外的所有錯誤 | 兜底異常處理 |
CREATE TABLE t (s1 INT PRIMARY KEY);
DELIMITER //
CREATE PROCEDURE handler_demo_exit()
BEGIN
DECLARE EXIT HANDLER FOR SQLSTATE '23000' BEGIN END; -- 靜默退出
SET @x = 1; INSERT INTO t VALUES (1);
SET @x = 2; INSERT INTO t VALUES (1); -- 觸發 23000,程序結束
SET @x = 3;
END//
DELIMITER ;
CALL handler_demo_exit(); SELECT @x; -- 結果:2(第三句未執行)
TRUNCATE TABLE t;
DELIMITER //
CREATE PROCEDURE handler_demo_continue()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' BEGIN END;
SET @x = 1; INSERT INTO t VALUES (1);
SET @x = 2; INSERT INTO t VALUES (1); -- 觸發 23000,但繼續
SET @x = 3;
END//
DELIMITER ;
CALL handler_demo_continue(); SELECT @x; -- 結果:3(全執行完)
ALTER TABLE t ADD s2 INT NOT NULL; -- 無預設值,INSERT 會產生警告 1364
DELIMITER //
CREATE PROCEDURE handler_combo()
BEGIN
DECLARE CONTINUE HANDLER FOR 1062 BEGIN END; -- 重複鍵忽略
DECLARE CONTINUE HANDLER FOR SQLWARNING
BEGIN UPDATE t SET s2 = 2; END; -- 警告時更新 s2=2
DECLARE CONTINUE HANDLER FOR 1364
BEGIN INSERT INTO t(s1,s2) VALUES (1,3); END; -- 欄位無預設值錯誤時插入新行
SET @x = 1; INSERT INTO t(s1) VALUES (1); -- 警告 1364 → 觸發第三個 HANDLER
SET @x = 2; INSERT INTO t(s1) VALUES (1); -- 錯誤 1062 → 觸發第一個 HANDLER
SET @x = 3;
END//
DELIMITER ;
CALL handler_combo();
SELECT * FROM t; -- 僅有一行 (1,3)
SELECT @x; -- 3
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
MySQL 預存程序異常處理機制雖不如 Oracle/PLSQL 豐富,但 DECLARE HANDLER 搭配 SQLSTATE/ERROR CODE/SQLWARNING/NOT FOUND/SQLEXCEPTION 已能覆蓋 90% 業務異常場景。關鍵在於:**精確識別條件值、選擇正確 handler_type、保持 HANDLER 邏輯極簡**。