web-dev-qa-db-fra.com

CTE en cours d'exécution dans une boucle infinie

Mon CTE fonctionne dans une boucle infinie pour un client spécifique et je ne suis pas capable de savoir pourquoi.

Voici la requête:

;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
6
Ashish

Je pense que cela devrait trouver le problème de problème pour vous. Il ajoute un LEVEL à votre hiérarchie, puis recherche un enregistrement d'identité individuel existant à plusieurs niveaux.

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

SELECT *
FROM ClassTree c1
WHERE EXISTS (SELECT 1 FROM ClassTree c2
              WHERE c2.id = c1.id
              AND c2.Level > c1.level)
3
JNK

Voici un petit quelque chose que vous pouvez utiliser pour trouver vos 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

Résultat:

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
8
Mikael Eriksson

La toute première chose que je ferais, c'est changer ceci:

JOIN ClassTree
     ON Parent_ID = ClassTree.ID 

pour ça:

JOIN ClassTree                         
     ON t.Parent_ID = ClassTree.ID 

Il peut être essentiel de rejoindre ClassTree à lui-même depuis que vous n'avez pas spécifié l'alias de table dans la jointure.

1
DForck42