Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'Invalid object name' error for Common Table Expression (CTE) even though CTE has been defined

Tags:

sql

sql-server

I am using SQL server 2012. I have three CTEs defined in a row as shown below:

;WITH X_CTE (A, B, C, D)
AS (
    ...
)
,
Y_CTE (A, B, C, D)
AS (
    ...
)
,
Z_CTE (A, B, C, D)
AS (
    ...
)

Then, I insert these CTEs into a table, whose schema is defined and matches that of the CTEs

INSERT INTO MyTable SELECT * FROM X_CTE
INSERT INTO MyTable SELECT * FROM Y_CTE
INSERT INTO MyTable SELECT * FROM Z_CTE

I am getting a 'Invalid object name' error for the CTEs in the three INSERT INTO statements. In fact, I get the same errors with SELECT statements:

SELECT * FROM X_CTE
SELECT * FROM Y_CTE
SELECT * FROM Z_CTE

Would you please point out what is wrong here?

Thanks

-Rohan.

like image 672
GigaRohan Avatar asked Dec 18 '13 01:12

GigaRohan


People also ask

Why would you see a common table expression CTE?

CTEs, like database views and derived tables, enable users to more easily write and maintain complex queries via increased readability and simplification. This reduction in complexity is achieved by deconstructing ordinarily complex queries into simple blocks to be used, and reused if necessary, in rewriting the query.

Why does SQL say invalid object name?

This typically means 1 of 2 things... you've referenced an object (table, trigger, stored procedure,etc) that doesn't actually exist (i.e., you executed a query to update a table, and that table doesn't exist). Or, the table exists, but you didn't reference it correctly...

What is CTE common table expression in SQL Server?

A common table expression, or CTE, is a temporary named result set created from a simple SELECT statement that can be used in a subsequent SELECT statement. Each SQL CTE is like a named query, whose result is stored in a virtual table (a CTE) to be referenced later in the main query.


2 Answers

The CTE's are defined only for one query. You would need to repeat them for the three selects or inserts:

with X_CTE . . .
INSERT INTO MyTable SELECT * FROM X_CTE;

with X_CTE . . .
INSERT INTO MyTable SELECT * FROM Y_CTE;

with X_CTE . . .
INSERT INTO MyTable SELECT * FROM Z_CTE;
like image 152
Gordon Linoff Avatar answered Sep 18 '22 13:09

Gordon Linoff


CTEs are only defined for one statement that follows them. Three INSERT statements are - well - more than one statement.

Since all of the inserts are to the same table, you can do a UNION ALL to gather all of the rows into a single INSERT statement:

INSERT INTO MyTable
SELECT * FROM X_CTE
UNION ALL
SELECT * FROM Y_CTE
UNION ALL
SELECT * FROM Z_CTE

But I'd also change the above to use explicit column lists - you don't want this query breaking if more columns are added to MyTable later:

INSERT INTO MyTable (A,B,C,D)
SELECT * FROM X_CTE
UNION ALL
SELECT * FROM Y_CTE
UNION ALL
SELECT * FROM Z_CTE
like image 41
Damien_The_Unbeliever Avatar answered Sep 19 '22 13:09

Damien_The_Unbeliever