CTE (Common Table Expression,通用資料表運算式) 是 SQL Server 2005 引入的暫時命名結果集,僅在單一陳述式 (`SELECT`, `INSERT`, `UPDATE`, `DELETE`, `CREATE VIEW`) 範圍內有效。CTE 不像暫存表佔用 `TempDB` 實體儲存,也不用像衍生表巢狀難以閱讀。本文透過分頁查詢實例展示 CTE 語法優勢,並介紹遞歸 CTE 應用場景。
WITH cte_name (column_list) AS
(
-- 定義查詢 (錨點成員)
SELECT ...
)
-- 緊接著單一陳述式引用 CTE
SELECT * FROM cte_name WHERE ...;
IF OBJECT_ID('t', 'U') IS NOT NULL DROP TABLE t;
GO
CREATE TABLE t (c1 INT, c2 DECIMAL, c3 INT);
GO
INSERT INTO t VALUES (1, 5.0, 10), (2, 5.5, 10), (3, 5.0, 20), (4, 5.5, 20);
GO
WITH t_cn AS
(
SELECT c1, c2, c3,
rn = ROW_NUMBER() OVER (ORDER BY c1 DESC)
FROM t
WHERE 1=1 -- 方便動態加條件
)
SELECT c1, c2, c3
FROM t_cn
WHERE rn BETWEEN 2 AND 3;
-- 同時取得總筆數 (分頁必要)
SELECT totalCn = COUNT(*) FROM t WHERE 1=1;
| 寫法 | 程式碼結構 | 可讀性 | 效能 |
|---|---|---|---|
| 巢狀衍生表 | `SELECT * FROM (SELECT *, ROW_NUMBER()... FROM (SELECT ... FROM t) a) b WHERE rn...` | ⭐⭐ (深層巢狀難追蹤) | 相同 |
| 暫存表 #temp | 建表 → 插入 → 查詢 → 刪除 | ⭐⭐⭐ (程序式) | 額外 TempDB I/O、鎖定 |
| CTE | `WITH t_cn AS (...) SELECT ... FROM t_cn WHERE ...` | ⭐⭐⭐⭐⭐ (線性閱讀、邏輯清晰) | 相同 (最佳化器展開) |
經典場景:員工組織架構、BOM 物料清單、分類樹狀結構。
-- 員工表:EmpId, MgrId, EmpName
WITH OrgChart AS
(
-- 錨點成員:最上層 (CEO, MgrId IS NULL)
SELECT EmpId, MgrId, EmpName, 0 AS Level
FROM Employee
WHERE MgrId IS NULL
UNION ALL
-- 遞歸成員:由上層往下查
SELECT e.EmpId, e.MgrId, e.EmpName, oc.Level + 1
FROM Employee e
INNER JOIN OrgChart oc ON e.MgrId = oc.EmpId
)
SELECT * FROM OrgChart
OPTION (MAXRECURSION 100); -- 防無限遞歸,預設 100,0=無限制
CTE 是 **T-SQL 可讀性與模組化的里程碑**。分頁查詢、複雜多步驟邏輯拆解、遞歸階層查詢、替代 View 簡化權限管理,皆為 CTE 強項。SQL Server 2005+ 專案**首選 CTE 取代衍生表與暫存表** (除非需重複多次引用或需索引/統計資訊)。