To find infinite recursive loop in CTE

后端 未结 6 386
梦如初夏
梦如初夏 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:47

    You can use the same approach described by Knuth for detecting a cycle in a linked list here. In one column, keep track of the children, the children's children, the children's children's children, etc. In another column, keep track of the grandchildren, the grandchildren's grandchildren, the grandchildren's grandchildren's grandchildren, etc.

    For the initial selection, the distance between Child and Grandchild columns is 1. Every selection from union all increases the depth of Child by 1, and that of Grandchild by 2. The distance between them increases by 1.

    If you have any loop, since the distance only increases by 1 each time, at some point after Child is in the loop, the distance will be a multiple of the cycle length. When that happens, the Child and the Grandchild columns are the same. Use that as an additional condition to stop the recursion, and detect it in the rest of your code as an error.

    SQL Server sample:

    declare @LinkTable table (Parent int, Child int);
    insert into @LinkTable values (1, 2), (1, 3), (2, 4), (2, 5), (3, 6), (3, 7), (7, 1);
    
    with cte as (
        select lt1.Parent, lt1.Child, lt2.Child as Grandchild
        from @LinkTable lt1
        inner join @LinkTable lt2 on lt2.Parent = lt1.Child
        union all
        select cte.Parent, lt1.Child, lt3.Child as Grandchild
        from cte
        inner join @LinkTable lt1 on lt1.Parent = cte.Child
        inner join @LinkTable lt2 on lt2.Parent = cte.Grandchild
        inner join @LinkTable lt3 on lt3.Parent = lt2.Child
        where cte.Child <> cte.Grandchild
    )
    select Parent, Child
    from cte
    where Child = Grandchild;
    

    Remove one of the LinkTable records that causes the cycle, and you will find that the select no longer returns any data.

提交回复
热议问题