變量是存儲過程邏輯控制的核心。本文系統梳理 MySQL 存儲過程中局部變量的聲明語法、作用域規則、賦值方式及常見陷阱,助你編寫健壯的過程化代碼。
DECLARE var_name [, var_name] ... type [DEFAULT value];
BEGIN ... END 塊的最開頭,先於任何其他語句。BEGIN ... END 及其嵌套塊內有效。DECLARE v_start_date DATE DEFAULT '2024-01-01';
DECLARE v_count INT DEFAULT 0;
DECLARE v_name VARCHAR(100);
SET var_name = expr [, var_name = expr] ...
expr 可以是常量、表達式、函數調用等任意返回值的合法表達式。
SET v_today = CURDATE();
SET v_start = DATE_SUB(CURDATE(), INTERVAL 1 MONTH), v_end = CURDATE();
SELECT col_name [, ...] INTO var_name [, ...] FROM table_expr ...
硬性要求: 查詢必須恰好返回 一行,否則報錯(0 行或 >1 行)。
CREATE FUNCTION get_balance(p_cust_id INT, p_as_of DATETIME)
RETURNS DECIMAL(10,2)
DETERMINISTIC
READS SQL DATA
BEGIN
DECLARE v_paid DECIMAL(10,2) DEFAULT 0;
SELECT IFNULL(SUM(amount), 0) INTO v_paid
FROM payment
WHERE cust_id = p_cust_id AND pay_date <= p_as_of;
RETURN v_paid; -- 簡化邏輯,實際可加總應收減實收
END;
| 錯誤場景 | 後果 | 修正 |
|---|---|---|
| DECLARE 放在非首行 | 語法錯誤 | 移至 BEGIN 後首行 |
| SELECT INTO 返回多行 | Runtime Error 1172 | 加 LIMIT 1 或聚合函數 |
| 變量名與列名衝突 | 歧義導致邏輯錯誤 | 變量加前綴 v_、p_ 區分 |
| 未初始化直接使用 | 值為 NULL 導致計算異常 | 聲明時用 DEFAULT 或緊跟 SET |
SET @x = 1 即可使用,無需聲明。存儲過程內優先用局部變量,避免副作用;需跨調用鏈傳遞狀態時才考慮會話變量。
掌握 DECLARE 位置規則、SET 與 SELECT INTO 兩種賦值模式、單行返回限制,即可駕馭 90% 存儲過程變量場景。良好的命名規範(v_ 開頭局部、p_ 開頭參數)與初始化習慣,能大幅減少調試時間。