遍历递归 CTE 到 SQL 服务器中的根达到最大递归

traversing recursive CTE to the root in SQL Server reaches maximum recursion

我有一组典型的员工和相应的经理,正如大多数递归 CTE 教程所使用的那样。我从 Uri Dimanttutorial.

的回答中得到的

与深度优先搜索不同,我的目标是输入员工 ID,查询 returns 经理列表直到根
因此,我调整了 JOIN 语句以将 manager id 从 CTE 连接到 employee ID。它应该获取某个员工的经理姓名。

导致错误:
The statement terminated. The maximum recursion 100 has been exhausted before statement completion.

我认为当递归到达管理器的最高级别时,它会 return 一个空的结果集,表明递归结束。

我想了解 SQL 引擎如何知道何时停止。 以及如何使此查询按我的预期工作。

谢谢

IF OBJECT_ID('Employees') IS NULL
BEGIN
    CREATE TABLE Employees
    (
    empid   int         NOT NULL,
    mgrid   int         NULL,
    empname nvarchar(25) NOT NULL,
    salary  money       NOT NULL,
    CONSTRAINT PK_Employees PRIMARY KEY(empid),
    CONSTRAINT FK_Employees_mgrid_empid
      FOREIGN KEY(mgrid)
      REFERENCES Employees(empid)
    )


    CREATE INDEX idx_nci_mgrid ON Employees(mgrid)
    SET NOCOUNT ON


    INSERT INTO Employees VALUES(1 , NULL, 'Nancy'   , 000.00)
    INSERT INTO Employees VALUES(2 , 1   , 'Andrew'  , 00.00)
    INSERT INTO Employees VALUES(3 , 1   , 'Janet'   , 00.00)
    INSERT INTO Employees VALUES(4 , 1   , 'Margaret', 00.00) 
    INSERT INTO Employees VALUES(5 , 2   , 'Steven'  , 00.00)
    INSERT INTO Employees VALUES(6 , 2   , 'Michael' , 00.00)
    INSERT INTO Employees VALUES(7 , 3   , 'Robert'  , 00.00)
    INSERT INTO Employees VALUES(8 , 3   , 'Laura'   , 00.00)
    INSERT INTO Employees VALUES(9 , 3   , 'Ann'     , 00.00)
    INSERT INTO Employees VALUES(10, 4   , 'Ina'     , 00.00)
    INSERT INTO Employees VALUES(11, 7   , 'David'   , 00.00)
    INSERT INTO Employees VALUES(12, 7   , 'Ron'     , 00.00)
    INSERT INTO Employees VALUES(13, 7   , 'Dan'     , 00.00)
    INSERT INTO Employees VALUES(14, 11  , 'James'   , 00.00)

END
GO
WITH EmpCTE
AS
( 

  -- Anchor Member (AM)
  SELECT 
      empid, 
      empname, 
      mgrid, 
      0 AS level                            -- <------------------- SET LVL START FROM 0
  
  FROM Employees
  WHERE EMPID = 7

  UNION ALL

  -- Recursive Member (RM)
  SELECT 
      e.empid, 
      e.empname, 
      e.mgrid, 
      e.level+1                     -- <------------------- INCREMENT LVL

manager id
  FROM Employees AS m
    JOIN EmpCTE AS e                    -- <------------------- RECURSIVELY CALL EmpCTE
      ON e.mgrid = m.empid
)

SELECT * FROM EmpCTE 


您已经成功创建了一个无限循环。您可以针对 level 使用过滤器来调试这些:

(也是在删除 manager id 之后)

WITH EmpCTE
AS
( 
  -- Anchor Member (AM)
  SELECT 
      empid, 
      empname, 
      mgrid, 
      0 AS level                            -- <------------------- SET LVL START FROM 0
  FROM Employees
  WHERE EMPID = 7
  UNION ALL
  -- Recursive Member (RM)
  SELECT 
      e.empid, 
      e.empname, 
      e.mgrid, 
      e.level+1                     -- <------------------- INCREMENT LVL
  FROM Employees AS m
    JOIN EmpCTE AS e                    -- <------------------- RECURSIVELY CALL EmpCTE
      ON e.mgrid = m.empid
where level < 2
)
SELECT * FROM EmpCTE;

empid       empname                   mgrid       level
----------- ------------------------- ----------- -----------
7           Robert                    3           0
7           Robert                    3           1
7           Robert                    3           2

这是因为您投影的是 EmpCTE as e 而不是 Employees as m 的列,所以您只是一次又一次地获得相同的数据(加上级别增加)。

WITH EmpCTE
AS
( 
  -- Anchor Member (AM)
  SELECT 
      empid, 
      empname, 
      mgrid, 
      0 AS level                            -- <------------------- SET LVL START FROM 0
  FROM Employees
  WHERE EMPID = 7
  UNION ALL
  -- Recursive Member (RM)
  SELECT 
      m.empid,   -- these columns need to come from m
      m.empname, -- these columns need to come from m
      m.mgrid,   -- these columns need to come from m
      e.level+1                     -- <------------------- INCREMENT LVL
  FROM Employees AS m
    JOIN EmpCTE AS e                    -- <------------------- RECURSIVELY CALL EmpCTE
      ON e.mgrid = m.empid
)
SELECT * FROM EmpCTE;

empid       empname                   mgrid       level
----------- ------------------------- ----------- -----------
7           Robert                    3           0
3           Janet                     1           1
1           Nancy                     NULL        2