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

MySQL 存儲過程實戰心得:變量、異常處理與 DELIMITER 陷阱

     編輯:MySQL 資料庫相關知識

案例代碼:主鍵衝突異常捕獲

USE test;
DROP TABLE IF EXISTS t8;
CREATE TABLE t8(s1 INT, PRIMARY KEY(s1));

DROP PROCEDURE IF EXISTS handlerdemo;
DELIMITER $$
CREATE PROCEDURE handlerdemo()
BEGIN
    DECLARE xx INT DEFAULT 4;
    -- 定義條件:SQLSTATE 23000 = 完整性約束違反
    DECLARE oh_no CONDITION FOR SQLSTATE '23000';
    -- 退出型處理器:遇到條件設置變量並退出 BEGIN...END
    DECLARE EXIT HANDLER FOR oh_no SET @info = '違反主鍵約束';
    
    SET @X = 1;
    INSERT INTO t8 VALUES(1);  -- 成功
    SET @X = 2;
    INSERT INTO t8 VALUES(1);  -- 觸發主鍵衝突,跳轉到 EXIT HANDLER
    SET @X = 3;                -- 不會執行
END $$
DELIMITER ;

-- 調用與驗證
CALL handlerdemo();
SELECT @X, @info;
-- 結果:@X=2, @info='違反主鍵約束'

核心心得總結

1. DELIMITER 陷阱與最佳實踐

  • 存儲過程視為「單條語句」,內部 ; 需被屏蔽,故重定義分隔符
  • 模式 A(推薦):定義前 DELIMITER //,結束後 DELIMITER ; 恢復,後續可繼續寫別的語句
  • 模式 B:定義前 DELIMITER $$,結束用 $$,但之後不能再寫其他語句,否則解析錯誤

2. 變量體系三層級

類型語法作用域聲明要求
局部變量DECLARE var INT;僅存儲過程內部必須聲明,置於 BEGIN 後首部
用戶變量@var會話級(跨存儲過程可見)無需聲明,直接賦值
系統變量@@session.var會話/全局只讀或特權修改

困惑點: 為何局部變量強制聲明位置,而用戶變量隨意用?這是 MySQL 歷史演進留下的不一致性。

3. 條件與處理器機制

-- 1. 定義條件別名
DECLARE oh_no CONDITION FOR SQLSTATE '23000';
-- 或直接用錯誤碼
DECLARE dup_key CONDITION FOR 1062;

-- 2. 綁定處理器
DECLARE EXIT HANDLER FOR oh_no SET @msg = '錯誤';
DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @retry = 1;
  • EXIT HANDLER:執行處理邏輯後退出當前 BEGIN...END 塊
  • CONTINUE HANDLER:執行處理邏輯後繼續執行後續語句
  • 可針對 SQLSTATE、MySQL 錯誤碼、SQLEXCEPTION、SQLWARNING、NOT FOUND

進階應用場景

  • 重試邏輯:CONTINUE HANDLER 捕獲死鎖,SLEEP() 後重試
  • 日誌記錄:EXIT HANDLER 寫入審計表再拋出
  • 事務保障:處理器中 ROLLBACK 確保一致性

官方文檔

MySQL 8.0 Condition Handling

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