Рекурсивная хранимая процедура — это процедура, которая вызывает саму себя в своем теле, создавая цикл выполнения. Это мощный инструмент для обработки иерархических данных.
Каждая рекурсивная процедура должна содержать:
CREATE PROCEDURE RecursiveFactorial @n INT, @result INT OUTPUT
AS
BEGIN
-- Базовый случай
IF @n <= 1
SET @result = 1
ELSE
BEGIN
-- Рекурсивный вызов
DECLARE @temp INT
EXEC RecursiveFactorial @n - 1, @temp OUTPUT
SET @result = @n * @temp
END
END;
CREATE PROCEDURE GetEmployeeHierarchy @managerId INT, @level INT = 0
AS
BEGIN
-- Вывод текущего уровня
SELECT e.id, e.name, @level as level
FROM employees e
WHERE e.manager_id = @managerId;
-- Рекурсивный вызов для подчиненных
DECLARE @subordinateId INT
DECLARE subordinate_cursor CURSOR FOR
SELECT id FROM employees WHERE manager_id = @managerId;
OPEN subordinate_cursor
FETCH NEXT FROM subordinate_cursor INTO @subordinateId
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC GetEmployeeHierarchy @subordinateId, @level + 1
FETCH NEXT FROM subordinate_cursor INTO @subordinateId
END
CLOSE subordinate_cursor
DEALLOCATE subordinate_cursor
END;
CREATE PROCEDURE FindPath @startNode INT, @endNode INT, @path VARCHAR(MAX) = ''
AS
BEGIN
SET @path = @path + CAST(@startNode AS VARCHAR) + '->'
IF @startNode = @endNode
PRINT @path
ELSE
BEGIN
DECLARE @nextNode INT
DECLARE edge_cursor CURSOR FOR
SELECT to_node FROM graph_edges WHERE from_node = @startNode;
OPEN edge_cursor
FETCH NEXT FROM edge_cursor INTO @nextNode
WHILE @@FETCH_STATUS = 0
BEGIN
IF CHARINDEX(CAST(@nextNode AS VARCHAR), @path) = 0
EXEC FindPath @nextNode, @endNode, @path
FETCH NEXT FROM edge_cursor INTO @nextNode
END
CLOSE edge_cursor
DEALLOCATE edge_cursor
END
END;
WITH EmployeeCTE AS (
-- Базовый случай
SELECT id, name, manager_id, 0 AS level
FROM employees
WHERE manager_id IS NULL
UNION ALL
-- Рекурсивная часть
SELECT e.id, e.name, e.manager_id, cte.level + 1
FROM employees e
JOIN EmployeeCTE cte ON e.manager_id = cte.id
)
SELECT * FROM EmployeeCTE;
CREATE PROCEDURE IterativeFactorial @n INT, @result INT OUTPUT
AS
BEGIN
SET @result = 1
WHILE @n > 1
BEGIN
SET @result = @result * @n
SET @n = @n - 1
END
END;
Рекурсивные хранимые процедуры — это мощный инструмент для:
✔ Обработки иерархических данных (деревья, графы)
✔ Решения задач с вложенной структурой
✔ Имплементации сложных алгоритмов
Лучшие практики:
Для большинства иерархических запросов в современных СУБД рекурсивные CTE предпочтительнее хранимых процедур.