建立方式
方式一:CREATE TABLE (推薦,可控結構)
-- 區域臨時表
CREATE TABLE #TmpStudent (
Tid INT IDENTITY(1,1) PRIMARY KEY,
Name VARCHAR(50) NOT NULL,
Age INT NULL
);
-- 全域臨時表
CREATE TABLE ##GlobalTmp (
Id INT PRIMARY KEY,
Data VARCHAR(100)
);
方式二:SELECT INTO (快速、推導結構)
SELECT * INTO #TmpStudent FROM Student WHERE Age > 20;
-- 等同於 CREATE TABLE #TmpStudent + INSERT ... SELECT
差異:SELECT INTO 鎖定 Tempdb 系統表 (sysobjects, sysindexes, syscolumns) 較久,高併發易阻塞;CREATE TABLE 僅鎖定極短時間,適合併發環境。大量單次載入用 SELECT INTO 較快。
方式三:直接在 Tempdb 建立 (持久化至重啟)
CREATE TABLE tempdb.dbo.PersistentTemp (Id INT PRIMARY KEY);
-- 不以 # 開頭,服務重啟前持續存在,需手動清理
刪除與清理
DROP TABLE #TmpStudent; -- 顯式刪除區域臨時表
DROP TABLE ##GlobalTmp; -- 顯式刪除全域臨時表
TRUNCATE TABLE #TmpStudent; -- 清空資料保留結構 (較 DELETE 快、不記錄逐列日誌)
生命週期與可見性
| 類型 | 前綴 | 可見範圍 | 自動清除時機 |
| 區域臨時表 | # | 當前 Session (含巢狀預存程序) | Session 結束、或建立它的預存程序結束 |
| 全域臨時表 | ## | 所有 Session | 建立 Session 結束 且 所有引用陳述式完成 |
| 持久 Tempdb 表 | 無 # | 所有 Session (權限允許) | 服務重啟 (依 model 重建時移除) |
關鍵行為細節
- 巢狀預存程序:子程序建立的
#tmp 對父程序同名 #tmp 遮蔽;子程序結束自動刪除,父程序繼續使用自己的 #tmp。
- 同名衝突:同一 Session 內不可建立同名區域臨時表 (除非巢狀層級不同)。
- 全域臨時表引用計數:Session A 建立
##G,Session B 查詢中。A 結束後,B 查詢完成前 ##G 仍存在;B 完成後自動刪除。
- 權限:任何使用者可建立臨時表;存取他人建立的全域臨時表需權限。
效能與最佳實務
- 預先定義結構:併發高用
CREATE TABLE,避免系統表鎖爭用。
- 加索引:大量資料 JOIN/篩選前建立非叢集索引 (
CREATE INDEX IX_#Tmp_Col ON #Tmp(Col)),統計資訊自動建立。
- 避免 SELECT * INTO 大表:記錄檔膨脹、鎖久。分批
INSERT ... SELECT 或使用最小記錄 (WITH (TABLOCK) + 簡單復原模式)。
- 及時清理:長執行程序中間結果用完即
DROP,釋放 Tempdb 空間與鎖。
- 表變數替代小資料集:<100 列、無 JOIN 大表、需避免重編譯時優先考慮表變數。
常見錯誤與排查
| 錯誤 | 原因 | 解決 |
| Invalid object name '#Tmp' | 跨 Session 引用區域臨時表 | 改用全域 ## 或傳遞表值參數 |
| There is already an object named '#Tmp' | 同 Session 重複建立 | 先 DROP 或檢查 OBJECT_ID |
| Tempdb 空間不足 | 大量臨時表未清理、自動成長受限 | 預設大檔案初始值、監控空間、及時 DROP |