WITH emp_CTE AS (
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS IdentityId, *
FROM dbo.employee )
SELECT * FROM emp_CTE
This works fine<
The CTE is part of the subsequent statement only.
The subsequent statement can be a single SELECT/INSERT/UPDATE/DELETE, or a compound (with UNION, INTERSECT etc)
For example:
;WITH cte1 AS
(
select ...
), cte2 AS
(
select ...
)
SELECT ...
UNION
SELECT ...;
The rule of thumb is that the scope is until where next ;
would be. A semi-colon terminates any statement but is optional unfortunately.
Your failing code above is actually this
...;
WITH emp_CTE AS (
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS IdentityId, *
FROM dbo.employee )
SELECT * FROM EMPLOYEES;
SELECT * FROM emp_CTE;
So the CTE is only in scope up until ...EMPLOYEES;
In short: NO. A CTE is valid exactly for the single, next statement - no more. And there's no way to "extend" the life of a CTE either.
From MSDN Books Online:
A common table expression (CTE) can be thought of as a temporary result set that is defined within the execution scope of a single SELECT, INSERT, UPDATE, DELETE, or CREATE VIEW statement. A CTE is similar to a derived table in that it is not stored as an object and lasts only for the duration of the query.
You can:
turn your CTE into a view and use that view for your queries - views are available as long as they are defined
store the results of the CTE into a temporary table or table variable for further processing
change your statements after the CTE so they can be executed as a single statement
WITH emp_CTE AS (
......)
SELECT (list of columns)
FROM emp_CTE
INNER JOIN dbo.Employees e ON ......