問題現場
-- 錯誤 1:區域變數加 @
CREATE PROCEDURE mypro()
BEGIN
DECLARE @temp INT; -- 報錯
SET @temp = 3;
END;
-- 錯誤 2:IN 參數加 @
CREATE PROCEDURE mypro(IN @temp INT)
BEGIN
SELECT * FROM t WHERE t.id > @temp;
END;
根本原因:MySQL 兩種變數體系
| 類型 | 語法 | 作用域 | 用途 | 範例 |
| 用戶變數 | @var_name | 會話級 (Session) | 跨語句傳值、客戶端互動 | SET @a = 1; SELECT @a; |
| 區域變數 | DECLARE var_name TYPE; | 程序/函數/觸發器區塊內 | 程序邏輯暫存、控制流程 | DECLARE cnt INT DEFAULT 0; |
| 參數 | IN/OUT/INOUT param_name TYPE | 程序調用期間 | 輸入/輸出/雙向傳值 | CREATE PROC p(IN id INT) |
正確寫法對照
-- 正確 1:區域變數不加 @
CREATE PROCEDURE mypro()
BEGIN
DECLARE temp INT DEFAULT 0; -- 無 @
SET temp = 3;
SELECT temp;
END;
-- 正確 2:IN 參數不加 @
CREATE PROCEDURE mypro(IN temp INT)
BEGIN
SELECT * FROM t WHERE t.id > temp; -- 直接用參數名
END;
-- 正確 3:用戶變數用於會話層傳值
CREATE PROCEDURE mypro()
BEGIN
SET @session_var = 100; -- 這裡用 @ 正確,因為是用戶變數
END;
-- 客戶端調用後可 SELECT @session_var 取得
常見混淆場景
SET @x = 1; 在程序外 → 用戶變數,正確。
DECLARE @x INT; 在程序內 → **語法錯誤**,區域變數不能有 @。
CREATE PROC p(IN @x INT) → **語法錯誤**,參數定義不能有 @。
SELECT @x; 在程序內 → 讀取用戶變數,正確(但易混淆,建議區域變數用不同命名慣例如 v_x)。
最佳命名慣例建議
- 區域變數:
v_name (variable)
- 參數:
p_name (parameter)
- 用戶變數:
@u_name (user) — 僅在需跨語句/會話共享時使用
