T-SQL:CTE别名的多次使用-不仅在外部查询中

T-SQL:CTE别名的多次使用-不仅在外部查询中,sql,tsql,common-table-expression,with-clause,Sql,Tsql,Common Table Expression,With Clause,当我在脚本中使用WITH子句时,我遇到了一个问题。这个问题很容易指出,我想多次使用CTE别名,而不仅仅是在外部查询中,这是问题的症结所在 例如: -- Define the CTE expression WITH cte_test (domain1, domain2, [...]) AS -- CTE query ( SELECT domain1, domain2, [...] FROM table ) -- Outer query SELECT * FROM cte_test

当我在脚本中使用WITH子句时,我遇到了一个问题。这个问题很容易指出,我想多次使用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
最后一行将导致以下错误,因为它位于外部查询之外:

Msg 208,16级,状态1,第12行无效对象名称“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
[...]
坦率地说,我不喜欢这个解决方案。其他人对此问题有最佳实践吗


提前谢谢

CTE仅在其所属SQL语句的作用域内。如果需要在后续语句中重用其数据,则需要一个临时表或表变量来存储数据。在您的示例中,除非您要实现递归CTE,否则我认为根本不需要CTE—您可以将其内容直接存储在临时表/表变量中,并根据需要重用它


还请注意,DELETE语句将尝试从基础表中删除,这与将结果放入临时表/表变量不同。

CommonTableExpression不会以任何方式持久化数据。它基本上只是在主查询之前创建子查询的一种方法

这使得它比普通子查询更像一个内嵌视图。因为您可以在一个查询中重复引用它,而不必一次又一次地键入它

但它仍然被视为一个视图,扩展到引用它的查询中,就像宏一样。根本没有数据的持久化


不幸的是,这意味着你必须自己坚持

  • 如果您希望CTE的逻辑被持久化,那么您不需要一个内嵌视图,您只需要一个视图

  • 如果希望CTE的结果集被持久化,则需要临时表类型的解决方案,例如您不喜欢的解决方案


你能通过使用
MERGE
语句来实现你的目标吗?也许可以使用
OUTPUT
子句,而不是
SELECT
作为你的CTE的消费者?为什么你想
从CTE中删除
?@Johan:进一步的语句不是重点,可以是任何其他DML语句,如
INSERT
&c。