首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 存儲過程異常處理機制:DECLARE HANDLER 精準捕獲錯誤碼

     編輯:MySQL 資料庫相關知識

異常處理架構

MySQL 存儲過程支持聲明式異常處理,三大核心組件:

  1. 條件聲明:DECLARE condition_name CONDITION FOR sqlstate/error_code
  2. 處理器聲明:DECLARE handler_type HANDLER FOR condition_name ...
  3. 處理動作:設置輸出參數、記錄日誌、回滾/繼續執行

處理器類型

完整示例:員工管理存儲過程

DELIMITER $$

CREATE PROCEDURE `sp_add_employee`(
  IN p_first_name VARCHAR(30),
  IN p_last_name VARCHAR(30),
  IN p_city VARCHAR(30),
  IN p_description VARCHAR(30),
  OUT p_sqlcode INT,
  OUT p_status_msg VARCHAR(100)
)
BEGIN
  /* 1. 聲明業務相關錯誤條件 */
  DECLARE duplicate_key CONDITION FOR 1062;      -- ER_DUP_ENTRY
  DECLARE foreign_key_violated CONDITION FOR 1216; -- ER_NO_REFERENCED_ROW_2
  
  /* 2. 聲明變量與游標 */
  DECLARE v_manager_id INT;
  DECLARE cur_mgr CURSOR FOR 
    SELECT id FROM employee 
    WHERE first_name = p_first_name AND last_name = p_last_name;
  
  /* 3. 聲明異常處理器 */
  DECLARE CONTINUE HANDLER FOR duplicate_key
  BEGIN
    SET p_sqlcode = 1062;
    SET p_status_msg = 'Duplicate key error';
  END;
  
  DECLARE CONTINUE HANDLER FOR foreign_key_violated
  BEGIN
    SET p_sqlcode = 1216;
    SET p_status_msg = 'Foreign key violated';
  END;
  
  DECLARE CONTINUE HANDLER FOR NOT FOUND
  BEGIN
    SET p_sqlcode = 1329;
    SET p_status_msg = 'No record found';
  END;
  
  /* 4. 業務邏輯 */
  SET p_sqlcode = 0;
  OPEN cur_mgr;
  FETCH cur_mgr INTO v_manager_id;
  
  IF p_sqlcode <> 0 THEN
    SET p_status_msg = CONCAT(p_status_msg, ' when fetching manager');
  ELSE
    INSERT INTO employee (first_name, manager_id, city, description)
    VALUES (p_first_name, v_manager_id, p_city, p_description);
    
    IF p_sqlcode <> 0 THEN
      SET p_status_msg = CONCAT(p_status_msg, ' when inserting employee');
    END IF;
  END IF;
  
  CLOSE cur_mgr;
END$$

DELIMITER ;

測試調用

SET @code = 0, @msg = '';
CALL sp_add_employee('Jason', 'Martin', 'New City', 'Desc', @code, @msg);
SELECT @code AS sqlcode, @msg AS message;

MySQL 常見錯誤碼速查

類型行為適用場景
CONTINUE執行處理動作後,**繼續**執行後續語句預期內錯誤(如重複鍵),記錄並跳過
EXIT執行處理動作後,**退出**當前 BEGIN...END 塊嚴重錯誤,需終止流程
UNDO執行處理動作後,**回滾**當前事務並退出需保證原子性的業務邏輯

進階技巧

1. GET DIAGNOSTICS 獲取詳細信息

DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
  GET DIAGNOSTICS CONDITION 1
    @errno = MYSQL_ERRNO,
    @state = RETURNED_SQLSTATE,
    @msg = MESSAGE_TEXT;
  SET p_status_msg = CONCAT('Error ', @errno, ' (', @state, '): ', @msg);
END;

2. 嵌套塊的異常傳播

內層塊無處理器時,異常向外層傳播;內層有 CONTINUE 處理器執行後,外層不再感知該異常。

3. 事務邊界與異常

  • 隱式事務:每條語句自動提交(autocommit=1)
  • 顯式事務:START TRANSACTION + COMMIT/ROLLBACK
  • UNDO HANDLER 自動回滾到事務起始點

最佳實踐

  1. 針對業務關鍵錯誤碼(1062、1216、1329)聲明專用條件
  2. 使用 CONTINUE 處理預期錯誤,EXIT/UNDO 處理嚴重錯誤
  3. 輸出參數返回統一錯誤碼 + 人類可讀消息,便於應用層處理
  4. 處理器中務必 DEALLOCATE PREPARE 清理動態 SQL 資源
  5. 避免在處理器中執行複雜邏輯,保持輕量

掌握 DECLARE ... HANDLER 機制,將錯誤處理從應用層下沉到存儲過程層,能顯著提升數據庫端的健壯性與可維護性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
錯誤碼SQLSTATE常量名含義
106223000ER_DUP_ENTRY重複鍵值
104823000ER_BAD_NULL_ERROR非空列插入 NULL
121623000ER_NO_REFERENCED_ROW_2外鍵約束失敗
121723000ER_ROW_IS_REFERENCED_2被引用行無法刪除
132902000ER_NO_DATA游標無數據 / NOT FOUND
1205HY000ER_LOCK_WAIT_TIMEOUT鎖等待超時
121340001ER_LOCK_DEADLOCK死鎖