2012-06-01 21 views
6

我有一個問題,當我在我的一個腳本中使用WITH子句時發生。這個問題很容易指出,我想多次使用CTE別名,而不是僅在外部查詢中使用CTE別名,並且存在癥結。T-SQL:多次使用CTE別名 - 不僅在外部查詢

例如:

-- Define the CTE expression 
WITH cte_test (domain1, domain2, [...]) 
AS 
-- CTE query 
(
    SELECT domain1, domain2, [...] 
    FROM table 
) 
-- Outer query 
SELECT * FROM cte_test 
-- Now I wanna use the CTE expression another time 
INSERT INTO sometable ([...]) SELECT [...] FROM cte_test 

最後一行將導致以下錯誤,因爲它是外部查詢外:

消息208,級別16,狀態1,行12無效的對象名稱'cte_test'。

有沒有辦法使用多次CTE的CTE?讓它持久?我目前的解決方案是創建一個臨時表,在這裏我存儲CTE的結果,並將此臨時表用於任何進一步的語句。

-- CTE 
[...] 
-- Create a temp table after the CTE block 
DECLARE @tmp TABLE (domain1 DATATYPE, domain2 DATATYPE, [...]) 
INSERT INTO @tmp (domain1, domain2, [...]) SELECT domain1, domain2, [...] FROM cte_test 
-- Any further DML statements 
SELECT * FROM @tmp 
INSERT INTO sometable ([...]) SELECT [...] FROM @tmp 
[...] 

坦率地說,我不喜歡這個解決方案。其他人是否有這個問題的最佳做法?

在此先感謝!

+0

你可以用'MERGE'語句,或許用'OUTPUT'子句,而不是'SELECT'作爲CTE的使用者來實現你的目標嗎? – HABO

+0

你爲什麼要從cte中「刪除」? – Johan

+1

@Johan:進一步的陳述不是重點,可以是任何其他DML語句,例如'INSERT'&c。 – Neil

回答

17

CommonTableExpression不以任何方式持久數據。這基本上只是在主查詢本身之前創建子查詢的一種方式。

這使得它比正常的子查詢更像是一個內聯視圖。因爲您可以在一個查詢中重複引用它,而不必一次又一次地輸入它。

但它仍然只是視爲一個視圖,擴展到引用它的查詢,宏像。根本沒有堅持數據。


這,不幸的是你,意味着你必須做的持久性自己。

  • 如果您希望CTE的邏輯持久化,您不需要一個內嵌視圖,您只需要一個視圖。

  • 如果您希望CTE的結果集被保留,您需要臨時表類型的解決方案,例如您不喜歡的解決方案類型。

9

CTE僅在其所屬的SQL語句的作用域中。如果您需要在後續語句中重用其數據,則需要臨時表或表變量來存儲數據。在您的示例中,除非您正在實現遞歸CTE,否則根本不需要CTE - 您可以將其內容直接存儲在臨時表格/表格變量中,並儘可能多地重複使用。

另請注意,如果您將結果放入臨時表/表變量中,您的DELETE語句將嘗試從基礎表中刪除。