首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 存儲過程異常處理機制深度解析:DECLARE HANDLER 語法、錯誤碼映射與實戰案例

     編輯:MySQL 綜合教學

MySQL 存儲過程通過 DECLARE ... HANDLER 捕獲運行時錯誤,實現「遇錯不中斷」或「優雅退出」的業務邏輯。本文系統梳理語法結構、條件值分類、SQLSTATE 與錯誤碼映射,並通過三個完整案例演示 EXIT、CONTINUE、SQLWARNING 三種處理器的行為差異。

一、標準語法結構

DECLARE handler_type HANDLER FOR condition_value[,...] statement

handler_type: CONTINUE | EXIT | UNDO  -- UNDO 暫不支援
condition_value:
  SQLSTATE [VALUE] sqlstate_value   -- ANSI/ODBC 標準 5 碼
  | condition_name                  -- 自定義條件名
  | SQLWARNING                      -- 所有 01 開頭警告
  | NOT FOUND                       -- 02 開頭 / 游標無數據
  | SQLEXCEPTION                    -- 除上述外所有錯誤
  | mysql_error_code                -- MySQL 原生數字錯誤碼

二、條件值三大速記類別

  • SQLWARNING:對應 01xxx 類警告(如截斷、舊密碼)。
  • NOT FOUND:對應 02xxx 類,含游標讀完、SELECT ... INTO 無行。
  • SQLEXCEPTION:除上述外的所有錯誤(含死鎖、鍵衝突等)。

查閱完整映射:https://dev.mysql.com/doc/refman/5.0/en/error-messages-server.html 或安裝目錄 share/mysql/errmsg.txt。

三、案例 1:EXIT HANDLER — 遇重複鍵即退出

CREATE TABLE t (s1 INT PRIMARY KEY);
DELIMITER //
CREATE PROCEDURE handlerdemo()
BEGIN
  DECLARE EXIT HANDLER FOR SQLSTATE '23000' BEGIN END;  -- 23000 = 完整性約束違規
  SET @x = 1; INSERT INTO t VALUES (1);
  SET @x = 2; INSERT INTO t VALUES (1);  -- 觸發 1062 / 23000,進入 HANDLER,結束過程
  SET @x = 3;  -- 不會執行
END//
DELIMITER ;

CALL handlerdemo(); SELECT @x;  -- 結果 @x = 2

行為:第二次 INSERT 報錯 → 進入 EXIT 處理器 → 直接離開 BEGIN...END 塊,後續語句不執行。

四、案例 2:CONTINUE HANDLER — 遇錯繼續往下跑

DROP PROCEDURE IF EXISTS handlerdemo;
DELIMITER //
CREATE PROCEDURE handlerdemo()
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 handlerdemo(); SELECT @x;  -- 結果 @x = 3

行為:錯誤被「吞掉」,流程無感知地繼續,最終 @x 為 3。

五、案例 3:混合處理警告與錯誤碼 — 實現「插入失敗則補齊默認值」

ALTER TABLE t ADD s2 INT NOT NULL;  -- 無默認值,插入時會產生 1364 警告/錯誤

DELIMITER //
CREATE PROCEDURE handlerdemo()
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                     -- Field doesn't have default value
    BEGIN INSERT INTO t(s1,s2) VALUES (1,3); END;       -- 改用顯式插入
  SET @x = 1; INSERT INTO t(s1) VALUES (1);
  SET @x = 2; INSERT INTO t(s1) VALUES (1);  -- 觸發 1062
  SET @x = 3;
END//
DELIMITER ;

CALL handlerdemo();
SELECT * FROM t;  -- 僅一行 (1,3)
SELECT @x;        -- 3

解析:首次插入觸發 1364 → 進入第三個 HANDLER 插入 (1,3);第二次插入觸發 1062 → 進入第一個 HANDLER 靜默忽略;最終 @x=3,數據唯一且完整。

六、最佳實踐建議

  1. 優先用 SQLSTATE:跨版本穩定,避免錯誤碼變更導致邏輯失效。
  2. 精準匹配:僅捕獲業務預期的錯誤(如 1062、1364),避免 SQLEXCEPTION 吞噬真實 Bug。
  3. 處理器體保持輕量:僅做日誌記錄、賦值、補償插入,嚴禁嵌套事務或長耗時操作。
  4. 配合 GET DIAGNOSTICS:MySQL 5.6+ 可在 HANDLER 內獲取詳細錯誤資訊,便於審計。

靈活運用異常處理器,能讓存儲過程在「脏數據、併發衝突、邊界條件」下依然保持健壯,是編寫企業級存儲邏輯的必備技能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved