2013-02-26 131 views
3

我有CTE查询,其上有大量记录。以前它工作得很好。但是最近,它会因一些成员带OPTION的无限循环CTE(maxrecursion 0)

终止该语句错误。报表完成前,最大递归100已用尽。

所以我把OPTION (maxrecursion 0)OPTION (maxrecursion 32767)我的查询,因为我不希望限制的记录。但是,结果是查询需要永久加载。我该如何解决这个问题?

这里是我的代码:

with cte as(
-- Anchor member definition 
    SELECT e.SponsorMemberID , e.MemberID, 1 AS Level 
    FROM tblMember AS e 
    where e.memberid = @MemberID 

union all 

-- Recursive member definition 
    select child.SponsorMemberID , child.MemberID, Level + 1 
    from tblMember child 

join cte parent 

on parent.MemberID = child.SponsorMemberID 
) 
-- Select the CTE result 
    Select distinct a.* 
    from cte a 
    option (maxrecursion 0) 

编辑:删除不必要的代码,很容易理解

解决:所以问题不是来自maxrecursion。它来自CTE。我不知道为什么,但可能它包含任何赞助商周期:A - > B - > C - > A - > ...(感谢@HABO)

我试过这种方法,它的工作原理。 Infinite loop in CTE when parsing self-referencing table

+0

您确定该数据不包含任何发起人循环:A - > B - > C - > A - > ...?还是自发赞助的会员? – HABO 2013-02-26 04:06:20

+0

你检查了查询计划吗?你有没有试图消除你的每个联接,首先检查cte,然后分别检查HigRank,gt,TotCust? – cha 2013-02-26 04:10:00

+0

HABO:不,tblMember上的成员具有唯一的值 cha:我认为查询工作正常。它工作,如果成员有一个小记录 – vantian 2013-02-26 04:20:34

回答

7

如果您正在达到递归限制,您可能在赞助关系或数据循环中具有相当的深度。像下面这样的查询将检测循环并终止递归:

declare @tblMember as Table (MemberId Int, SponsorMemberId Int); 
insert into @tblMember (MemberId, SponsorMemberId) values 
    (1, 2), (2, 3), (3, 5), (4, 5), (5, 1), (3, 3); 
declare @MemberId as Int = 3; 
declare @False as Bit = 0, @True as Bit = 1; 

with Children as (
    select MemberId, SponsorMemberId, 
    Convert(VarChar(4096), '>' + Convert(VarChar(10), MemberId) + '>') as Path, @False as Loop 
    from @tblMember 
    where MemberId = @MemberId 
    union all 
    select Child.MemberId, Child.SponsorMemberId, 
    Convert(VarChar(4096), Path + Convert(VarChar(10), Child.MemberId) + '>'), 
    case when CharIndex('>' + Convert(VarChar(10), Child.MemberId) + '>', Path) = 0 then @False else @True end 
    from @tblMember as Child inner join 
     Children as Parent on Parent.MemberId = Child.SponsorMemberId 
    where Parent.Loop = 0) 
    select * 
    from Children 
    option (MaxRecursion 0); 
+0

我运行这个查询,是成功的,但没有结果。这是否意味着CTE上没有循环? – vantian 2013-02-26 06:13:05

+0

嗨HABO,我解决了这个问题。请检查我的更新。感谢提示 – vantian 2013-02-26 06:47:34

+0

@vantian - 你没有得到任何行'循环'是'1'?您是否在查询中将两个'@ tblMember'都更改为'tblMember'?只是好奇,因为你喜欢的答案使用了一种相当类似的技术来跟踪路径/级别以定位循环。 – HABO 2013-02-26 13:46:33