To find infinite recursive loop in CTE

后端 未结 6 389
梦如初夏
梦如初夏 2020-12-16 00:55

I\'m not a SQL expert, but if anybody can help me.

I use a recursive CTE to get the values as below.

Child1 --> Parent 1

Parent1 --> Parent 2

6条回答
  •  不知归路
    2020-12-16 01:27

    Here is the solution for SQL Server:

    Table Insert script:

    CREATE TABLE MyTable
    (
        [ID] INT,
        [ParentID] INT,
        [Name] NVARCHAR(255)
    );
    
    INSERT INTO MyTable
    (
        [ID],
        [ParentID],
        [Name]
    )
    VALUES
    (1, NULL, 'A root'),
    (2, NULL, 'Another root'),
    (3, 1, 'Child of 1'),
    (4, 3, 'Grandchild of 1'),
    (5, 4, 'Great grandchild of 1'),
    (6, 1, 'Child of 1'),
    (7, 8, 'Child of 8'),
    (8, 7, 'Child of 7'), -- This will cause infinite recursion
    (9, 1, 'Child of 1');
    

    Script to find the exact records which are the culprit:

    ;WITH RecursiveCTE
    AS (
       -- Get all parents: 
       -- Any record in MyTable table could be an Parent
       -- We don't know here yet which record can involve in an infinite recursion.
       SELECT ParentID AS StartID,
              ID,
              CAST(Name AS NVARCHAR(255)) AS [ParentChildRelationPath]
       FROM MyTable
       UNION ALL
    
       -- Recursively try finding all the childrens of above parents
       -- Keep on finding it until this child become parent of above parent.
       -- This will bring us back in the circle to parent record which is being
       -- keep in the StartID column in recursion
       SELECT RecursiveCTE.StartID,
              t.ID,
              CAST(RecursiveCTE.[ParentChildRelationPath] + ' -> ' + t.Name AS NVARCHAR(255)) AS [ParentChildRelationPath]
       FROM RecursiveCTE
           INNER JOIN MyTable AS t
               ON t.ParentID = RecursiveCTE.ID
       WHERE RecursiveCTE.StartID != RecursiveCTE.ID)
    
    -- FInd the ones which causes the infinite recursion
    SELECT StartID,
           [ParentChildRelationPath],
           RecursiveCTE.ID
    FROM RecursiveCTE
    WHERE StartID = ID
    OPTION (MAXRECURSION 0);
    

    Output of above query:

提交回复
热议问题