變量與條件處理是編寫健壯存儲過程的基石。本文通過完整可運行示例,系統講解 DECLARE/SET/SELECT ... INTO 三種賦值方式、會話變量與局部變量區別、條件定義與處理器(CONTINUE/EXIT/UNDO)的實戰模式。
CREATE PROCEDURE sp_demo(IN p_dept INT, OUT p_cnt INT)
BEGIN
DECLARE v_name VARCHAR(20) DEFAULT 'Chen'; -- 無 @ 符號
DECLARE v_id INT DEFAULT 0;
-- 業務邏輯
SELECT COUNT(*) INTO p_cnt FROM employee WHERE depid = p_dept;
END;
-- 給已聲明局部變量賦值
SET v_name = 'Wang';
-- 直接定義並賦值會話變量(帶 @,跨存儲過程可見)
SET @session_var = 100;
SELECT COUNT(*) INTO v_id FROM employee WHERE depid = p_dept AND name = v_name;
-- 也可直接賦給 OUT 參數
SELECT COUNT(*) INTO p_cnt FROM employee WHERE depid = p_dept;
DECLARE handler_type HANDLER FOR condition_value sp_statement
handler_type: CONTINUE | EXIT | UNDO
condition_value:
SQLSTATE '23000' -- 具體 SQL 狀態碼
| 1062 -- MySQL 錯誤碼
| condition_name -- 自定義條件名
| SQLWARNING -- 01 開頭狀態碼
| NOT FOUND -- 02 開頭狀態碼
| SQLEXCEPTION -- 其餘所有錯誤
| 模式 | handler_type | 行為 | 典型用途 |
|---|---|---|---|
| 定義條件名 + EXIT | EXIT | 遇錯立即終止存儲過程 | 關鍵業務不可重試,需快速失敗 |
| SQLSTATE + CONTINUE | CONTINUE | 記錄錯誤標記,繼續執行後續語句 | 批量導入容忍部分主鍵衝突 |
| SQLEXCEPTION + 事務控制 | CONTINUE | 統一捕獲異常,最後判斷提交/回滾 | 多步寫入操作的原子性保證 |
CREATE PROCEDURE sp_batch_insert()
BEGIN
DECLARE v_err INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET v_err = 1;
START TRANSACTION;
INSERT INTO t1 VALUES (1, 'a');
INSERT INTO t1 VALUES (2, 'b'); -- 假設此處主鍵衝突
INSERT INTO t1 VALUES (3, 'c');
IF v_err = 1 THEN
ROLLBACK;
ELSE
COMMIT;
END IF;
END;
DECLARE 必須置於 BEGIN 之後、所有業務語句之前,否則報錯。SELECT ... INTO 若查無結果,變量保持原值且觸發 NOT FOUND 條件,建議配合 DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done=1; 處理。UNDO handler(MySQL 尚未實現)。SQLSTATE > mysql_error_code > SQLEXCEPTION,具體優先匹配。掌握變量作用域與條件處理器組合拳,能讓存儲過程從「能跑」進化為「可控、可觀測、可恢復」的生產級組件。