Difference between CTE and Temp Table and Table Variable

Estimated study time: 14 minutes. A clear, side-by-side comparison to help you pick the right temporary data structure.

SQL Server gives you three common ways to hold intermediate result sets: a CTE (Common Table Expression), a Temp Table, and a Table Variable. They look similar on the surface but behave very differently under the hood.

What is a CTE?

A CTE is a named, temporary result set defined using WITH that exists only for the duration of a single query. It is not physically stored anywhere — SQL Server expands it into the query at execution time.

WITH HighEarners AS (
    SELECT EmpName, Salary
    FROM Employees
    WHERE Salary > 50000
)
SELECT * FROM HighEarners ORDER BY Salary DESC;

What is a Temp Table?

A temp table (#TempTable or ##GlobalTempTable) is a real table created in tempdb. It supports indexes, constraints, and statistics, and it persists for the life of the session or connection, not just one query.

CREATE TABLE #HighEarners (EmpName VARCHAR(100), Salary INT);
INSERT INTO #HighEarners
SELECT EmpName, Salary FROM Employees WHERE Salary > 50000;

SELECT * FROM #HighEarners;

What is a Table Variable?

A table variable (DECLARE @Table TABLE (...)) also lives in tempdb but behaves more like a variable: its scope is limited to the batch or procedure in which it's declared, and it doesn't participate in transaction rollbacks the same way a temp table does.

DECLARE @HighEarners TABLE (EmpName VARCHAR(100), Salary INT);
INSERT INTO @HighEarners
SELECT EmpName, Salary FROM Employees WHERE Salary > 50000;

SELECT * FROM @HighEarners;

Key Differences

AspectCTETemp TableTable Variable
StorageNot stored, expanded into querytempdb (physical table)tempdb (variable)
ScopeSingle statementSession/connectionBatch/procedure
IndexesNot supportedSupportedLimited (PK/unique only)
StatisticsNoneMaintained by optimizerNot maintained (assumes 1 row)
Reusable across queriesNoYesYes
Best forRecursive queries, readabilityLarge data sets, complex logicSmall data sets inside a procedure
💡 Tip: Use a CTE for readability or recursion, a Temp Table when you're working with large data and need indexes/statistics, and a Table Variable for small, short-lived data inside a single batch or function.

Ready to go beyond the basics?

Get hands-on training, live mentorship, and placement support with Uncodemy's Data Analytics Course.

Explore Data Analytics Course →