Common Table Expressions (CTEs) and Recursive CTEs in SQL Server Explained

Written by

in

Common Table Expressions (CTEs) and Recursive CTEs in SQL Server Explained

A CTE is a named subquery that makes complex queries genuinely readable — and recursive CTEs solve a problem plain SQL can’t touch at all: hierarchies of unknown, variable depth.

Recursive CTE: Climbing the Tree★ ANCHOR: level 0Priya (CEO)manager_id = NULLMiguellevel 1Aishalevel 1Liamlevel 2JOIN back to CTE,level + 1 each passGotcha: a bad circular manager_id would recurse forever —MAXRECURSION 100 (the default) stops it automatically. 📌

A Basic CTE

WITH RegionSummary AS (
    SELECT region, SUM(amount) AS total_sales
    FROM dbo.Sale
    GROUP BY region
)
SELECT region, total_sales FROM RegionSummary WHERE total_sales > 10000;

Notice this achieves what Chapter 4’s Fundamentals lesson said WHERE can’t do directly — filter on an aggregate — without needing HAVING, because the aggregate is computed inside the CTE first, then the outer query treats total_sales as an ordinary column. A CTE is purely an organizational tool for readability; this exact query could be written as a subquery in FROM instead, with identical results.

Recursive CTE: Walking a Hierarchy

CREATE TABLE dbo.OrgChart (
    employee_id INT PRIMARY KEY,
    name        NVARCHAR(50) NOT NULL,
    manager_id  INT NULL REFERENCES dbo.OrgChart(employee_id)
);
INSERT INTO dbo.OrgChart VALUES (1,'Priya (CEO)',NULL), (2,'Miguel',1), (3,'Aisha',1), (4,'Liam',2);

WITH OrgHierarchy AS (
    -- Anchor: top of the hierarchy
    SELECT employee_id, name, manager_id, 0 AS level
    FROM dbo.OrgChart WHERE manager_id IS NULL

    UNION ALL

    -- Recursive: joins back to the CTE itself, one level deeper each pass
    SELECT o.employee_id, o.name, o.manager_id, oh.level + 1
    FROM dbo.OrgChart o
    INNER JOIN OrgHierarchy oh ON o.manager_id = oh.employee_id
)
SELECT REPLICATE('  ', level) + name AS org_tree, level FROM OrgHierarchy ORDER BY level, name;

This is a problem that genuinely cannot be solved with a fixed number of JOINs, because you don’t know upfront how many management levels deep an org chart goes — it could be 3 levels or 15, and a plain query has to be written for a specific, known number of hops. Recursion is the only tool in standard SQL that handles “unknown depth.”

How Recursion Actually Runs

Anchor Starting rows (level 0) Recursive member Joins to itself, +1 level each pass

SQL Server stops automatically once a pass produces zero new rows. A CTE doesn’t persist anywhere and can’t be indexed — it only exists for the single statement it’s attached to, unlike the temp tables from Chapter 3.

The Infinite Loop Trap

-- A circular reference (Aisha reports to Liam, who reports to Aisha) would recurse forever
-- without a safety net. SQL Server defaults to a hard cap of 100 recursion levels:
SELECT * FROM dbo.OrgChart OPTION (MAXRECURSION 100); -- the implicit default

-- Msg 530 fires automatically once that cap is hit on genuinely bad/circular data:
-- "The statement terminated. The maximum recursion 100 has been exhausted..."

-- You can raise or lower the cap explicitly (0 = unlimited, use with real caution)
;WITH OrgHierarchy AS (...)
SELECT * FROM OrgHierarchy OPTION (MAXRECURSION 50);
Common mistake: Assuming your hierarchy data is always clean and skipping any thought about MAXRECURSION. Real org charts, category trees, and bill-of-materials data occasionally do contain a bad circular reference from a data-entry mistake — the default 100-level cap is what turns that into a clear error instead of a runaway query.
Practice tip: Add a fifth employee to OrgChart reporting to Liam (level 3), rerun the query, and confirm the indentation deepens correctly. Then deliberately create a circular reference (set Priya’s manager_id to Liam’s employee_id) and watch the MAXRECURSION error fire — seeing the safety net trigger for real is worth more than reading about it.

Enjoyed this?

Subscribe to get every new SQL Server lesson as soon as it’s published, and share it with a developer who’d find it useful.

📡 Subscribe via RSS  | 
Share on X  | 
Share on LinkedIn  | 
Share on Facebook

Want the full structured course with quizzes, projects, and 10+ exercises per chapter? Check out SQL Server for Developers & DBAs, coming soon on this site.