T-SQL:CTE别名的多次使用-不仅在外部查询中
当我在脚本中使用WITH子句时,我遇到了一个问题。这个问题很容易指出,我想多次使用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
-- 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。