語法結構
DECLARE handler_type HANDLER FOR condition_value[,...] statement
handler_type: CONTINUE | EXIT | UNDO (暫不支持)
condition_value:
SQLSTATE [VALUE] sqlstate_value
| condition_name
| SQLWARNING -- 01xxx 類警告
| NOT FOUND -- 02xxx 類、游標結束
| SQLEXCEPTION -- 除上述外所有錯誤
| mysql_error_code
處理器類型行為對比
| 類型 | 執行 statement 後 | 適用場景 |
CONTINUE | 繼續執行後續語句 | 記錄日志、設置標記、嘗試修復後繼續 |
EXIT | 退出當前 BEGIN...END 塊 | 嚴重錯誤不可恢復、終止事務 |
UNDO | 回滾並退出(MySQL 暫不支持) | — |
條件值速記對照表
| 速記 | 對應 SQLSTATE 類別 | 典型場景 |
SQLWARNING | 01xxx | 數據截斷、非法值轉換、索引不存在等警告 |
NOT FOUND | 02xxx | SELECT ... INTO 無結果、游標到達末尾 |
SQLEXCEPTION | 其他 | 主鍵衝突、外鍵違反、語法錯誤、權限不足等 |
實戰示例 1:主鍵衝突 EXIT 處理
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); -- 重複鍵錯誤,觸發 HANDLER,退出 BEGIN...END
SET @x = 3; -- 不會執行
END//
DELIMITER ;
CALL handler_demo_exit();
SELECT @x; -- 結果: 2
實戰示例 2:主鍵衝突 CONTINUE 處理
DROP PROCEDURE IF EXISTS handler_demo_cont;
DELIMITER //
CREATE PROCEDURE handler_demo_cont()
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); -- 錯誤但繼續
SET @x = 3; -- 執行
END//
DELIMITER ;
CALL handler_demo_cont();
SELECT @x; -- 結果: 3
實戰示例 3:多條件處理器鏈
ALTER TABLE t ADD s2 INT NOT NULL; -- 無默認值
DELIMITER //
CREATE PROCEDURE handler_multi()
BEGIN
DECLARE CONTINUE HANDLER FOR 1062 BEGIN END; -- 主鍵衝突
DECLARE CONTINUE HANDLER FOR SQLWARNING -- 警告 (如 1364 字段無默認值)
BEGIN
UPDATE t SET s2 = 2; -- 修復操作
END;
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,觸發第 2 個 HANDLER 插入 (1,3)
SET @x = 2;
INSERT INTO t(s1) VALUES (1); -- 錯誤 1062,觸發第 1 個 HANDLER 忽略
SET @x = 3;
END//
DELIMITER ;
CALL handler_multi();
SELECT * FROM t; -- 結果: (1,3)
SELECT @x; -- 結果: 3
錯誤碼查找方法
- MySQL 安裝目錄
share/mysql/errmsg.txt
- 命令行工具:
perror 1062 → Duplicate entry
- 官方文檔:Server Error Codes and Messages
最佳實踐建議
- 優先使用 SQLSTATE:標準化、跨版本穩定(如 '23000' 代表完整性約束違反)。
- 具體錯誤碼處理器置前:MySQL 按聲明順序匹配,先匹配具體碼(1062),再匹配類別(SQLEXCEPTION)。
- 處理器內避免複雜邏輯:僅做日志記錄、變量標記、簡單修復,防止遞歸觸發。
- 事務邊界清晰:
EXIT HANDLER 會隱式回滾當前事務(若在事務中)。
- 游標 NOT FOUND 必須處理:否則游標循環會意外終止。