Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Aplica-se a:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Azure Synapse Analytics
Sistema de Plataforma de Análise (PDW)
Banco de dados SQL no Microsoft Fabric
Uma CTE (expressão de tabela comum) fornece a vantagem significativa de poder fazer referência a si mesma, criando assim uma CTE recursiva. Um CTE recursivo é aquele em que um CTE inicial é executado repetidamente para retornar subconjuntos de dados até que o conjunto de resultados completo seja obtido.
Uma consulta é conhecida como uma consulta recursiva quando faz referência a uma CTE recursiva. Retornar dados hierárquicos é um uso comum de consultas recursivas. Por exemplo, exibir funcionários em um gráfico organizacional ou dados em um cenário de cobrança de materiais no qual um produto pai tem um ou mais componentes e esses componentes podem ter subcomponentes, ou podem ser componentes, de outros pais.
Uma CTE recursiva pode simplificar muito o código necessário para executar uma consulta recursiva dentro de uma SELECTinstrução, , INSERTUPDATEDELETECREATE VIEW ou instrução. Em versões anteriores do SQL Server, uma consulta recursiva geralmente requer o uso de tabelas temporárias, cursores e lógica para controlar o fluxo das etapas recursivas. Para obter mais informações sobre expressões de tabela comuns, consulte WITH common_table_expression.
No Microsoft Fabric, no Fabric Data Warehouse e no ponto de extremidade de análise do SQL, ambos dão suporte a CTEs padrão, sequenciais e aninhados, mas não a CTEs recursivas.
Estrutura de um CTE recursivo
A estrutura da CTE recursiva em Transact-SQL é semelhante a rotinas recursivas em outras linguagens de programação. Embora uma rotina recursiva em outras linguagens retorne um valor escalar, uma CTE recursiva pode retornar várias linhas.
Um CTE recursivo consiste em três elementos:
Invocação da rotina.
A primeira invocação do CTE recursivo consiste em uma ou mais definições de consulta CTE unidas por
UNION ALLoperadores,UNIONouEXCEPTINTERSECToperadores. Como essas definições de consulta formam o conjunto de resultados base da estrutura CTE, elas são conhecidas como membros de âncora.As definições de consulta CTE são consideradas membros de âncora, a menos que referenciem a própria CTE. Todas as definições de consulta de membro de âncora devem ser posicionadas antes da primeira definição de membro recursivo e um
UNION ALLoperador deve ser usado para ingressar o último membro de âncora com o primeiro membro recursivo.Invocação recursiva da rotina.
A invocação recursiva inclui uma ou mais definições de consulta CTE unidas por
UNION ALLoperadores que fazem referência à própria CTE. Essas definições de consulta são conhecidas como membros recursivos.Verificação de encerramento.
A verificação de término está implícita; a recursão é interrompida quando nenhuma linha é retornada da invocação anterior.
Note
Um CTE recursivo composto incorretamente pode causar um loop infinito. Por exemplo, se a definição de consulta do membro recursivo retornar os mesmos valores para as colunas pai e filho, um loop infinito será criado. Ao testar os resultados de uma consulta recursiva, você pode limitar o número de níveis de recursão permitidos para uma instrução específica usando a MAXRECURSION dica e um valor entre 0 e 32.767 na OPTION cláusula da INSERTinstrução , UPDATEou DELETESELECT instrução.
Para obter mais informações, consulte:
Pseudocódigo e semântica
A estrutura de CTE recursiva deve conter pelo menos um membro de âncora e um membro recursivo. O pseudocódigo a seguir mostra os componentes de um CTE recursivo simples que contém um único membro de âncora e um único membro recursivo.
WITH cte_name ( column_name [ ,...n ] )
AS
(
CTE_query_definition -- Anchor member is defined.
UNION ALL
CTE_query_definition -- Recursive member is defined referencing cte_name.
)
-- Statement using the CTE
SELECT *
FROM cte_name
A semântica da execução recursiva é a seguinte:
- Divida a expressão CTE em membros de ancoragem e recursivos.
- Execute os membros de âncora criando a primeira invocação ou conjunto de resultados base (
T0). - Execute os membros recursivos com
Tiuma entrada eTi+ 1 como saída. - Repita a etapa 3 até que um conjunto vazio seja retornado.
- Retorne o conjunto de resultados. Este é um
UNION ALLdeT0paraTn.
Examples
O exemplo a seguir mostra a semântica da estrutura de CTE recursiva retornando uma lista hierárquica de funcionários, começando pelo funcionário de alto escalão, no AdventureWorks2025 banco de dados. Um passo a passo da execução de código segue o exemplo.
Crie uma tabela de funcionários:
CREATE TABLE dbo.MyEmployees
(
EmployeeID SMALLINT NOT NULL,
FirstName NVARCHAR (30) NOT NULL,
LastName NVARCHAR (40) NOT NULL,
Title NVARCHAR (50) NOT NULL,
DeptID SMALLINT NOT NULL,
ManagerID INT NULL,
CONSTRAINT PK_EmployeeID PRIMARY KEY CLUSTERED (EmployeeID ASC)
);
Preencha a tabela com valores:
INSERT INTO dbo.MyEmployees
VALUES
(1, N'Ken', N'Sánchez', N'Chief Executive Officer', 16, NULL),
(273, N'Brian', N'Welcker', N'Vice President of Sales', 3, 1),
(274, N'Stephen', N'Jiang', N'North American Sales Manager', 3, 273),
(275, N'Michael', N'Blythe', N'Sales Representative', 3, 274),
(276, N'Linda', N'Mitchell', N'Sales Representative', 3, 274),
(285, N'Syed', N'Abbas', N'Pacific Sales Manager', 3, 273),
(286, N'Lynn', N'Tsoflias', N'Sales Representative', 3, 285),
(16, N'David', N'Bradley', N'Marketing Manager', 4, 273),
(23, N'Mary', N'Gibson', N'Marketing Specialist', 4, 16);
USE AdventureWorks2008R2;
GO
WITH DirectReports (ManagerID, EmployeeID, Title, DeptID, Level)
AS (
-- Anchor member definition
SELECT e.ManagerID,
e.EmployeeID,
e.Title,
edh.DepartmentID,
0 AS Level
FROM dbo.MyEmployees AS e
INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON e.EmployeeID = edh.BusinessEntityID
AND edh.EndDate IS NULL
WHERE ManagerID IS NULL
UNION ALL
-- Recursive member definition
SELECT e.ManagerID,
e.EmployeeID,
e.Title,
edh.DepartmentID,
Level + 1
FROM dbo.MyEmployees AS e
INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON e.EmployeeID = edh.BusinessEntityID
AND edh.EndDate IS NULL
INNER JOIN DirectReports AS d
ON e.ManagerID = d.EmployeeID)
-- Statement that executes the CTE
SELECT ManagerID,
EmployeeID,
Title,
DeptID,
Level
FROM DirectReports
INNER JOIN HumanResources.Department AS dp
ON DirectReports.DeptID = dp.DepartmentID
WHERE dp.GroupName = N'Sales and Marketing'
OR Level = 0;
GO
Passo a passo de código de exemplo
O CTE DirectReportsrecursivo define um membro de âncora e um membro recursivo.
O membro de âncora retorna o conjunto T0de resultados base. Este é o funcionário mais alto da empresa. Ou seja, um funcionário que não se reporta a um gerente.
Aqui está o conjunto de resultados retornado pelo membro de âncora:
ManagerID EmployeeID Title Level
--------- ---------- ----------------------------- ------
NULL 1 Chief Executive Officer 0
O membro recursivo retorna os subordinados diretos do funcionário no conjunto de resultados do membro de âncora. Isso é obtido por uma operação de junção entre a tabela Funcionário e a DirectReports CTE. É essa referência à própria CTE que estabelece a invocação recursiva. Com base no funcionário no CTE DirectReports como entrada (Ti), a junção (MyEmployees.ManagerID = DirectReports.EmployeeID) retorna como saída (Ti + 1), os funcionários que têm (Ti) como gerente.
Portanto, a primeira iteração do membro recursivo retorna este conjunto de resultados:
ManagerID EmployeeID Title Level
--------- ---------- ----------------------------- ------
1 273 Vice President of Sales 1
O membro recursivo é ativado repetidamente. A segunda iteração do membro recursivo usa o conjunto de resultados de linha única na etapa 3 (contendo um EmployeeID de ) como o valor de 273entrada e retorna este conjunto de resultados:
ManagerID EmployeeID Title Level
--------- ---------- ----------------------------- ------
273 16 Marketing Manager 2
273 274 North American Sales Manager 2
273 285 Pacific Sales Manager 2
A terceira iteração do membro recursivo usa o conjunto de resultados anterior como o valor de entrada e retorna este conjunto de resultados:
ManagerID EmployeeID Title Level
--------- ---------- ----------------------------- ------
16 23 Marketing Specialist 3
274 275 Sales Representative 3
274 276 Sales Representative 3
285 286 Sales Representative 3
O conjunto de resultados final retornado pela consulta em execução é a união de todos os conjuntos de resultados gerados pela âncora e membros recursivos.
Veja aqui o conjunto de resultados.
ManagerID EmployeeID Title Level
--------- ---------- ----------------------------- ------
NULL 1 Chief Executive Officer 0
1 273 Vice President of Sales 1
273 16 Marketing Manager 2
273 274 North American Sales Manager 2
273 285 Pacific Sales Manager 2
16 23 Marketing Specialist 3
274 275 Sales Representative 3
274 276 Sales Representative 3
285 286 Sales Representative 3