HiveBrain v1.2.0
Get Started
← Back to all entries
patternsqlMinor

CTE Running in Infinite Loop

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
loopinfiniterunningcte

Problem

My CTE runs in an infinite loop for a specific customer and I am not able to find out why.

Here is the query:

;WITH ClassTree
           AS (SELECT ID, NAME, Parent_ID
               FROM   TableName
               WHERE  ID = 1
               UNION ALL
               SELECT T.ID, T.NAME, T.Parent_ID
               FROM   TableName T WITH (NOLOCK)
                      JOIN ClassTree
                        ON Parent_ID = ClassTree.ID
)
SELECT * FROM ClassTree

Solution

Here is a little something that you can use to find your cycles.

declare @T table
(
  ID int,
  Parent_ID int
)

insert into @T values
(1, 3),(2, 1),(3, 2),    -- This is a cycle
(4, 4),                  -- This is a cycle
(5, null),(6, 5),(7, 6)  -- This is not a cycle

;with C as
(
  select T.ID,
         T.Parent_ID,
         cast(',' + cast(ID as varchar(10)) + ',' as varchar(max)) as Path,
         0 Cycle
  from @T as T
  union all
  select T.ID,
         T.Parent_ID,
         C.Path + cast(T.ID as varchar(10)) + ',',
         case when C.Path like '%,'+cast(T.ID as varchar(10))+',%' 
           then 1 
           else 0 
         end
  from @T as T
    inner join C  
      on T.Parent_ID = C.ID
  where C.Cycle = 0
)
select *
from C
where Cycle = 1


Result:

ID          Parent_ID   Path       Cycle
----------- ----------- ---------- -----------
4           4           ,4,4,      1
3           2           ,3,1,2,3,  1
2           1           ,2,3,1,2,  1
1           3           ,1,2,3,1,  1

Code Snippets

declare @T table
(
  ID int,
  Parent_ID int
)

insert into @T values
(1, 3),(2, 1),(3, 2),    -- This is a cycle
(4, 4),                  -- This is a cycle
(5, null),(6, 5),(7, 6)  -- This is not a cycle

;with C as
(
  select T.ID,
         T.Parent_ID,
         cast(',' + cast(ID as varchar(10)) + ',' as varchar(max)) as Path,
         0 Cycle
  from @T as T
  union all
  select T.ID,
         T.Parent_ID,
         C.Path + cast(T.ID as varchar(10)) + ',',
         case when C.Path like '%,'+cast(T.ID as varchar(10))+',%' 
           then 1 
           else 0 
         end
  from @T as T
    inner join C  
      on T.Parent_ID = C.ID
  where C.Cycle = 0
)
select *
from C
where Cycle = 1
ID          Parent_ID   Path       Cycle
----------- ----------- ---------- -----------
4           4           ,4,4,      1
3           2           ,3,1,2,3,  1
2           1           ,2,3,1,2,  1
1           3           ,1,2,3,1,  1

Context

StackExchange Database Administrators Q#16111, answer score: 9

Revisions (0)

No revisions yet.