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

MySQL 預存程序變量:DECLARE 局部變量 vs @ 會話變量深度解析

     編輯:MySQL 資料庫相關知識

前言:兩種變量,截然不同的生命週期

在編寫 MySQL 預存程序時,DECLARE 與 SET @var 定義的變量常讓開發者困惑。本文透過實例演示,徹底釐清「局部變量」與「會話變量」的作用域、生命週期、可見性差異,助你避開共享狀態導致的 Bug。

一、核心差異速覽

特性DECLARE 變量@ 會話變量
作用域僅在 BEGIN ... END 區塊內整個會話(連線)期間
生命週期程序結束即銷毀連線斷開或顯式清除前持久
可見性僅當前程序可見同一連線的所有程序、SQL 可見
語法DECLARE var_name type [DEFAULT value];SET @var_name = value;(無需宣告)
類型檢查強型別,宣告時固定動態型別,賦值時決定
典型用途暫存計算、流程控制、遊標變量跨程序傳值、會話級配置、除錯追蹤

二、實戰演示:同一程序多次呼叫的行為差異

-- 1. 建立測試程序
DROP PROCEDURE IF EXISTS temp;
DELIMITER //
CREATE PROCEDURE temp()
BEGIN
    DECLARE a INT DEFAULT 1;   -- 局部變量
    SET a = a + 1;
    SET @b = @b + 1;           -- 會話變量
    SELECT a, @b;
END //
DELIMITER ;

-- 2. 初始化會話變量
SET @b = 1;

-- 3. 連續呼叫三次
CALL temp();  -- 結果:a=2, @b=2
CALL temp();  -- 結果:a=2, @b=3
CALL temp();  -- 結果:a=2, @b=4

觀察:

  • a 每次呼叫都重新初始化為 1,遞增後為 2,不保留上次呼叫的值。
  • @b 在會話層面持久化,每次呼叫在上次基礎上遞增,跨呼叫共享狀態。

三、進階場景:巢狀程序與會話變量傳遞

CREATE PROCEDURE outer_proc()
BEGIN
    SET @shared = 'init';
    CALL inner_proc();
    SELECT @shared;  -- 可見 inner_proc 的修改
END;

CREATE PROCEDURE inner_proc()
BEGIN
    SET @shared = 'modified';
    -- 也可直接 SELECT @shared 讀取 outer 設定的值
END;

這使得會話變量成為「跨程序通信」的輕量管道,但也帶來隱性耦合風險:程序不再純粹,副作用難以追蹤。

四、最佳實踐建議

  1. 預設使用 DECLARE:封裝邏輯、避免副作用、利於測試與並發。
  2. 僅在必要時用會話變量:如跨多個獨立程序傳遞狀態、動態 SQL 構建中暫存識別符、應用層需讀取的運行時參數。
  3. 命名規範區分:局部變量用 v_ 前綴(如 v_count),會話變量用 @sv_(如 @sv_config),一眼辨識作用域。
  4. 避免在觸發器/事件中濫用會話變量:它們無固定會話上下文,行為不可預期。
  5. 清理習慣:會話變量用完執行 SET @var = NULL; 或連線池回收時重置,防止殘留汙染後續業務。

五、常見誤區澄清

  • 誤區:「SET @x = 1 等同於 DECLARE x INT DEFAULT 1」 → 錯,前者無類型約束、作用域全域。
  • 誤區:「會話變量是全域變量」 → 不精確,它是「連線級」,不同連線互不干擾;真正的全域變量是 @@global.xxx 系統變量。
  • 誤區:「DECLARE 可以在程序中間宣告」 → 必須在 BEGIN 之後、任何語句之前集中宣告。

理解變量作用域是編寫健壯預存程序的基石。堅持「高內聚、低耦合」,讓 DECLARE 成為主力,會話變量只作精準補刀,你的程序將更易維護、除錯與擴展。

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