在CTE中查找无限递归循环

编程入门 行业动态 更新时间:2024-10-28 10:37:10
本文介绍了在CTE中查找无限递归循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我不是SQL专家,但是如果有人可以帮助我.

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

我使用递归CTE获取以下值.

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

Child1-> Parent 1

Child1 --> Parent 1

父母1->父母2

Parent2-> NULL

Parent2 --> NULL

如果数据填充出错,那么我将遇到以下类似情况,因为该情况,CTE可能会进入无限递归循环并给出最大递归错误.由于数据量很大,因此我无法手动检查此不良数据.请让我知道是否有办法找到它.

If data population has gone wrong, then I'll have something like below, because of which CTE may go to infinite recursive loop and gives max recursive error. Since the data is huge, I cannot check this bad data manually. Please let me know if there is a way to find it out.

Child1-> Parent 1

Child1 --> Parent 1

Parent1-> Child1

Parent1 --> Child1

Child1-> Parent 1

Child1 --> Parent 1

Parent1-> Parent2

Parent1 --> Parent2

Parent2-> Child1

Parent2 --> Child1

推荐答案

您尚未指定方言或列名,因此很难给出完美的示例...

You haven't specified the dialect or your column names, so it is difficult to make the perfect example...

-- Some random data IF OBJECT_ID('tempdb..#MyTable') IS NOT NULL DROP TABLE #MyTable CREATE TABLE #MyTable (ID INT PRIMARY KEY, ParentID INT NULL, Description VARCHAR(100)) INSERT INTO #MyTable (ID, ParentID, Description) VALUES (1, NULL, 'Parent'), -- Try changing the second value (NULL) to 1 or 2 or 3 (2, 1, 'Child'), -- Try changing the second value (1) to 2 (3, 2, 'SubChild') -- End random data ;WITH RecursiveCTE (StartingID, Level, Parents, Loop, ID, ParentID, Description) AS ( SELECT ID, 1, '|' + CAST(ID AS VARCHAR(MAX)) + '|', 0, * FROM #MyTable UNION ALL SELECT R.StartingID, R.Level + 1, R.Parents + CAST(MT.ID AS VARCHAR(MAX)) + '|', CASE WHEN R.Parents LIKE '%|' + CAST(MT.ID AS VARCHAR(MAX)) + '|%' THEN 1 ELSE 0 END, MT.* FROM #MyTable MT INNER JOIN RecursiveCTE R ON R.ParentID = MT.ID AND R.Loop = 0 ) SELECT StartingID, Level, Parents, MAX(Loop) OVER (PARTITION BY StartingID) Loop, ID, ParentID, Description FROM RecursiveCTE ORDER BY StartingID, Level

类似的东西将显示递归cte中是否存在循环.查看列Loop.照原样处理数据,没有循环.在注释中,有一些示例,说明了如何更改值以引起循环.

Something like this will show if/where there are loops in the recursive cte. Look at the column Loop. With the data as is, there is no loops. In the comments there are examples on how to change the values to cause a loop.

最后,递归cte以|id1|id2|id3|的形式创建ID的VARCHAR(MAX)(称为Parents),然后检查当前的ID是否已在该列表"中.如果是,则将Loop列设置为1.在递归联接(ABD R.Loop = 0)中检查此列.

In the end the recursive cte creates a VARCHAR(MAX) of ids in the form |id1|id2|id3| (called Parents) and then checks if the current ID is already in that "list". If yes, it sets the Loop column to 1. This column is checked in the recursive join (the ABD R.Loop = 0).

结尾查询使用将整个块"链的Loop列设置为1.

The ending query uses a MAX() OVER (PARTITION BY ...) to set to 1 the Loop column for a whole "block" of chains.

稍微复杂一点,生成一个更好"的报告:

A little more complex, that generates a "better" report:

-- Some random data IF OBJECT_ID('tempdb..#MyTable') IS NOT NULL DROP TABLE #MyTable CREATE TABLE #MyTable (ID INT PRIMARY KEY, ParentID INT NULL, Description VARCHAR(100)) INSERT INTO #MyTable (ID, ParentID, Description) VALUES (1, NULL, 'Parent'), -- Try changing the second value (NULL) to 1 or 2 or 3 (2, 1, 'Child'), -- Try changing the second value (1) to 2 (3, 3, 'SubChild') -- End random data -- The "terminal" childrens (that are elements that don't have childrens -- connected to them) ;WITH WithoutChildren AS ( SELECT MT1.* FROM #MyTable MT1 WHERE NOT EXISTS (SELECT 1 FROM #MyTable MT2 WHERE MT1.ID != MT2.ID AND MT1.ID = MT2.ParentID) ) , RecursiveCTE (StartingID, Level, Parents, Descriptions, Loop, ParentID) AS ( SELECT ID, -- StartingID 1, -- Level '|' + CAST(ID AS VARCHAR(MAX)) + '|', '|' + CAST(Description AS VARCHAR(MAX)) + '|', 0, -- Loop ParentID FROM WithoutChildren UNION ALL SELECT R.StartingID, -- StartingID R.Level + 1, -- Level R.Parents + CAST(MT.ID AS VARCHAR(MAX)) + '|', R.Descriptions + CAST(MT.Description AS VARCHAR(MAX)) + '|', CASE WHEN R.Parents LIKE '%|' + CAST(MT.ID AS VARCHAR(MAX)) + '|%' THEN 1 ELSE 0 END, MT.ParentID FROM #MyTable MT INNER JOIN RecursiveCTE R ON R.ParentID = MT.ID AND R.Loop = 0 ) SELECT * FROM RecursiveCTE WHERE ParentID IS NULL OR Loop = 1

此查询应返回所有最后一个孩子"行以及完整的父链.如果没有循环,列Loop是0,如果存在循环,列1.

This query should return all the "last child" rows, with the full parent chain. The column Loop is 0 if there is no loop, 1 if there is a loop.

更多推荐

在CTE中查找无限递归循环

本文发布于:2023-10-16 12:36:11,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1497568.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:递归   CTE

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!