| 特性 | 表變數 (@Table) | 臨時表 (#Table / ##Table) |
|---|---|---|
| 作用域 | 當前批次 (Batch),不跨預存程序/函數 | 區域 (#):當前 Session,跨巢狀預存程序 全域 (##):所有 Session,建立 Session 結束且無引用時刪除 |
| 建立方式 | DECLARE @t TABLE (...) | CREATE TABLE #t (...) 或 SELECT ... INTO #t |
| 名稱長度 | 128 字元 (系統內部自動產生唯一名稱) | 116 字元 (系統附加後綴) |
| 資料類型 | 可用使用者定義型別、XML Schema Collection | 需在 Tempdb 預先定義 UDT/XML Schema |
| 排序規則 | 繼承目前資料庫 | 繼承 Tempdb |
DECLARE 時定義 (PK、UNIQUE 隱含索引、CHECK、DEFAULT)。事後不可 DDL (無 CREATE INDEX/ALTER TABLE)。CREATE INDEX、ALTER TABLE ADD COLUMN、ADD CONSTRAINT。支援命名約束 (但多使用者同名衝突風險)。| 操作 | 表變數 | 臨時表 |
|---|---|---|
| INSERT ... EXEC | SQL 2000 不支援,2005+ 支援 | 全版本支援 |
| SELECT ... INTO | 不支援 | 支援 |
| TRUNCATE TABLE | 不支援 | 支援 |
| SET IDENTITY_INSERT | 不支援 | 支援 |
| 統計資訊 | 不建立,優化器假設 1 列 | 自動建立/更新,依實際列數產生計畫 |
| 重編譯 | 不觸發 | 可能觸發 (DDL、統計變更) |
| 交易/回滾 | 僅 DML 期間短暫交易,回滾不影響表變數內容 | 完整交易語意,回滾會還原資料 |
DECLARE @t TABLE (Id INT PRIMARY KEY CLUSTERED, Code CHAR(10) UNIQUE NONCLUSTERED);sys.objects 不可見。正確做法直接在作用域內引用變數名。測試環境:AdventureWorks.Sales.SalesOrderDetail × 10 (約 12 萬列),依 ModifiedDate JOIN 原表。
結論:需與大表 JOIN 或複雜查詢時,臨時表完勝。表變數適合小資料集 (<100 列)、單純暫存、函數回傳、避免重編譯場景。
SELECT INTO / INSERT EXEC / TRUNCATE?→ 臨時表。無絕對優劣,只有場景適配度。建議:開發階段以表變數起步,遇到效能瓶頸 (估計列數偏差、計畫差) 遷移至臨時表;生產環境關鍵 ETL/報表直接採用臨時表 + 適當索引。定期用 SET STATISTICS IO, TIME ON 對比驗證。