通用資料表運算式(CTEs)
通用資料表運算式 (Common Table Expression) 是 SQL 2005 才開始支援的查詢語法。 它有二個主要的用途:簡化子查詢與遞迴查詢。
通用資料表(CTE)
CTE 就像是一個暫存性資料表或者暫存檢視,你可以在 CTE_query_definition 中使用 SELECT 語法建立這個暫時性的資料表。
語法:
WITH <CteName> AS [(ColName[,...n])] ( -- CTE_query_definition ) -- outer query
在通用資料表中的 CTE_query_definition ,不能使用下列項目:
- ORDER BY (除非指定了 TOP 子句)
 - INTO
 - 含有查詢提示的 OPTION 子句
 - FOR XML
 - FOR BROWSE
 
例一:當做暫存表使用
WITH OrderItems AS ( SELECT OrderID, COUNT(*) as ItemCounts FROM OrderDetails GROUP BY OrderID ) --在 WITH 定義後,緊接者 SELECT 查詢 SELECT O.OrderID, OI.ItemCounts FROM Orders O INNER JOIN OrderItems OI ON O.OrderID=OI.OrderID
前面提過,CTE可以用來簡化子查詢,所以上面例子可以等於以下語法:
SELECT O.OrderID, OD.ItemCounts FROM Orders O LEFT JOIN ( SELECT OrderID, COUNT(*) as ItemCounts FROM OrderDetails GROUP BY OrderID ) as OD ON O.OrderID=OD.OrderID
前面提過,CTE就像一個暫存資料表,所以在 CTE 後面,你可以使用任何 DML 來參考這個暫存資料表。
DELETE OrderDetails FROM OrderDetails, OrderItems WHERE OrderDetails.OrderID=OrderItems.OrderID AND OrderItems.ItemCounts>10
例二:定義多個 CTE
非遞迴的 CTE 允許同時定義多個 CTE 查詢
WITH OrderTable(OrderID, CustomerID) AS ( SELECT OrderID, CustomerID FROM Orders ), OrderDetail(OrderID, Total) AS ( SELECT OrderID, SUM(UnitPrice*Quantity) as Total FROM OrderDetails GROUP BY OrderID ) SELECT O.OrderID, O.CustomerID, OD.Total FROM OrderTable O INNER JOIN OrderDetail OD ON O.OrderID=OD.OrderID
遞迴通用資料表(Recursive CTE)
遞迴 CTE 的 CTE_query_definition 包含二個部份:錨點部分和遞迴部分。
- 錨點部分:當作遞迴查詢的初始資料,使用 UNION ALL 和遞迴部分的查詢結果結合。
 - 遞迴部分:透過遞迴方式,與 CTE 反覆執行。
 
語法:
WITH <CteName> AS [(ColName[,...n])]
(
    --CTE_query_definition
	-- 1) anchor member 錨點部分
	UNION ALL
	-- 2) recursive member 遞迴部分
)
-- outer query
使用上注意事項
遞迴 CTE 的查詢定義中包含二個部份:錨點部分和遞迴部分。且必須符合以下限制:
- 使用下列運算子組合: UNION ALL 、 UNION 、 INTERSECT 或 EXCEPT 。
 - 但是最後一個錨點和第一個遞迴之間只能使用 UNION ALL 運算子組合。
 - 錨點和遞迴的欄位數要相同。
 - 錨點和遞迴的欄位型別也要相同。
 - 遞迴成員的 FROM 子句只能參考 CTE expression_name 一次
 
在遞迴通用資料表中的 CTE_query_definition ,不能使用下列項目:
- SELECT DISTINCT
 - PIVOT
 - HAVING
 - Aggregation
 - TOP
 - LEFT、RIGHT、OUTER JOIN (允許 INNER JOIN)
 - 子查詢
 - 適用於 CTE_query_definition 內 CTE 之遞迴參考的提示。
 
OPTION 子句
在 CTE 語法中,你可以透過 OPTION 子句來設定 MAXRECURSION 屬性,以定義遞迴的最高層次。 當遞迴層次超過指定的大小就會引發錯誤。例如:
WITH cteOrg (OrgID, CName, level) AS
(
    /*第一部分為 Anchor Member , 指不會被遞迴呼叫到的部分  */ 
	SELECT OrgID, CName, 1
	FROM tblOrganization
	WHERE ParentID is Null
    UNION ALL
    /*會在遞迴過程中反覆執行, 直到無任何查詢結果為止   */ 
	SELECT Org.OrgID, Org.CName, level+1
	FROM tblOrganization Org
	INNER JOIN cteOrg ON cteOrg.OrgID = Org.ParentID
)
SELECT * FROM cteOrg
OPTION (MAXRECURSION 5);
; WITH
因為 WITH 這個關鍵字用在許多表達式中,所以,若一個 CTE 表達式的第一行不是由 WITH 開始,就必須加上分號(semicolon)來斷行。例如:
;WITH cteOrg (OrgID, CName, OrgPath, level) AS
(
	SELECT OrgID, CName, cast(OrgID as varchar(200)) as OrgPath, 0
	FROM tblOrganization
	WHERE ParentID is Null
	UNION ALL
	SELECT Org.OrgID, Org.CName, cast(OrgPath+'/'+Org.OrgID as varchar(200)), level+1
	FROM tblOrganization Org
	INNER JOIN cteOrg ON cteOrg.OrgID = Org.ParentID
)
SELECT OrgID, Replicate('  ',level)+CName, OrgPath FROM cteOrg


沒有留言:
張貼留言