Question

I've got a question which occurs when I was using the WITH-clause in one of my script. The question is easy to pointed out I wanna use the CTE alias multiple times instead of only in outer query and there is crux.

For instance:

-- 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

The last row will lead to the following error because it's outside the outer query:

Msg 208, Level 16, State 1, Line 12 Invalid object name 'cte_test'.

Is there a way to use the CTE multiple times resp. make it persistent? My current solution is to create a temp table where I store the result of the CTE and use this temp table for any further statements.

-- 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
[...]

Frankly, I don't like this solution. Does anyone else have a best practice for this problem?

Thanks in advance!

Was it helpful?

Solution

A CommonTableExpression doesn't persist data in any way. It's basically just a way of creating a sub-query in advance of the main query itself.

This makes it much more like an in-line view than a normal sub-query would be. Because you can reference it repeatedly in one query, rather than having to type it again and again.

But it is still just treated as a view, expanded into the queries that reference it, macro like. No persisting of data at all.


This, unfortunately for you, means that you must do the persistance yourself.

  • If you want the CTE's logic to be persisted, you don't want an in-line view, you just want a view.

  • If you want the CTE's result set to be persisted, you need a temp table type of solution, such as the one you do not like.

OTHER TIPS

A CTE is only in scope for the SQL statement it belongs to. If you need to reuse its data in a subsequent statement, you need a temporary table or table variable to store the data in. In your example, unless you're implementing a recursive CTE I don't see that the CTE is needed at all - you can store its contents straight in a temporary table/table variable and reuse it as much as you want.

Also note that your DELETE statement would attempt to delete from the underlying table, unlike if you'd placed the results into a temporary table/table variable.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top