變數是 T-SQL 程式設計的核心狀態容器。理解區域變數與全域變數的生命週期、可見範圍、賦值語法、資料型別限制,能避免作用域洩漏、型別轉換錯誤、並發衝突等隱性 Bug。
DECLARE @變數名 資料型別 [, @變數名 資料型別 ...]
BEGIN...END) 內宣告的變數,外層不可見。| 方式 | 語法 | 特性 | 建議場景 |
|---|---|---|---|
SET | SET @var = 運算式 | ANSI 標準、單一變數、回傳錯誤若多筆結果 | 單一標量賦值、程式碼可攜性要求 |
SELECT | SELECT @var = 運算式 或 SELECT @v1=col1, @v2=col2 FROM ... | 可一次賦值多變數、查詢多筆時取最後一筆 (不報錯) | 從資料表查詢賦值、多變數同時賦值 |
範例 4-5:宣告並賦值
DECLARE @id char(10);
SELECT @id = '10010001';
範例 4-6:查詢結果直接賦值多變數
USE pangu;
DECLARE @name char(30), @wage money;
SELECT @name = e_name, @wage = e_wage
FROM employee
WHERE emp_id = '10010001';
SELECT @name AS e_name, @wage AS e_wage;
-- 結果: 張三 8000.0000
@select, @from, @where),雖然加 @ 前綴通常安全,但動態 SQL 拼接時可能產生語法歧義。sys.dm_exec_describe_first_result_set 或線上叢書附錄查詢完整保留字清單。| 特性 | 說明 |
|---|---|
| 命名 | 以 @@ 開頭 (雙 @ 符號),系統預先定義,使用者不可自訂。 |
| 作用域 | 伺服器層級,所有連線/批次/程序均可存取。 |
| 內容 | 系統配置值、效能統計、連線狀態、錯誤資訊、版本資訊等。 |
| 權限 | 唯讀 (大多數),少數可透過 sp_configure 間接影響。 |
| 變數 | 含義 | 典型用途 |
|---|---|---|
@@ERROR | 最近一條陳述式錯誤號 (0=成功) | 錯誤處理流程控制 |
@@ROWCOUNT | 最近一條陳述式影響列數 | 判斷 UPDATE/DELETE 是否生效 |
@@IDENTITY | 最近插入的身分識別值 (跨範圍/觸發器) | 取得新建主鍵值 (注意觸發器副作用) |
SCOPE_IDENTITY() | 目前範圍內最近插入的身分識別值 | 較 @@IDENTITY 安全,推薦使用 |
@@TRANCOUNT | 目前交易巢狀層級 | 交易管理、避免巢狀交易洩漏 |
@@VERSION | SQL Server 版本資訊字串 | 版本相容性檢查、稽核報表 |
@@SERVERNAME | 伺服器網路名稱 | 多實例環境識別、動態 SQL 建構 |
@@SPID | 目前連線的 Server Process ID | 鎖定分析、死結追蹤、動態 SQL 相關 |
| 陷阱 | 後果 | 正確做法 |
|---|---|---|
| 區域變數未宣告直接賦值 | 編譯錯誤 "Must declare the scalar variable" | 嚴格遵循 DECLARE → SET/SELECT 順序 |
| SELECT 賦值查詢回傳多筆 | 變數取最後一筆,邏輯錯誤無警告 | 加 TOP 1 / 聚合 / WHERE 唯一鍵 確保單筆 |
| 混淆 @var 與 @@global | 語法錯誤或讀取錯誤資訊 | 記住:單 @ = 區域,雙 @@ = 全域 |
| 字元型別未指定長度 | 預設長度 1,資料截斷無警告 | 永遠明確指定長度:varchar(100) |
| 預存程式參數與區域變數同名 | 參數遮蔽區域變數,難以除錯 | 命名區分:參數 @p_*,區域 @v_*,迴圈 @i_* |
變數管理看似瑣碎,實則是程式可靠度的基石。建立團隊「變數命名與使用規範」,納入靜態程式碼分析規則 (如 TSQLSmells、ScriptDOM 自訂規則),從源頭消除變數相關缺陷。