识别导致错误的查询中的行?

时间:2014-05-22 11:52:52

标签: sql sql-server tsql

我已经做了一些阅读,看着有类似问题的人,但只是通过使用TOP手动查找问题来缩小范围。

这是我过去为查找违规记录所做的工作。

我想知道是否有更强大的东西可以更普遍地使用。

我的查询是:

; WITH x AS ( SELECT b.ParentPartId,
                  b.ChildPartId,
                  b.ChildPartQty,
                  b.ConsumingWorkCenterId
           FROM jbds.BoM b
           UNION ALL
           SELECT lb.ParentPartId,
                  lb.ChildPartId,
                  lb.ChildPartQty,
                  lb.ConsumingWorkCenterId
           FROM jbds.BoM lb
           INNER JOIN x ON lb.ParentPartId = x.ChildPartId ) 
SELECT *
FROM x
WHERE ConsumingWorkCenterId IS NULL

我得到的错误是:

  

Msg 530,Level 16,State 1,Line 1   声明终止。在语句完成之前,最大递归100已经用尽。

我知道你可以使用TOP并最终找到有问题的记录,但我想知道是否有更好的解决方案来使用TOP而不是慢慢浏览记录?

2 个答案:

答案 0 :(得分:1)

跟踪递归级别不会解决此问题。 为了重新创建错误,我写了这段代码:

drop table #temp 
GO
create table #temp (
    ParentPartId int,
    ChildPartId int
)
GO

truncate table #temp
GO
insert into #temp(ParentPartId,ChildPartId)
values (1,2),(2,3),(3,1)
GO

;WITH x AS ( 
    SELECT 
        b.ParentPartId,
        b.ChildPartId
    FROM #temp b
    UNION ALL
    SELECT 
        lb.ParentPartId,
        lb.ChildPartId
    FROM #temp lb
    INNER JOIN x 
        ON lb.ParentPartId = x.ChildPartId 
) 
SELECT 
    *
FROM x

如果您跟踪递归,您会发现在101级,值将为(2,3)。但这并不意味着这一行出了问题。在您的表中有一个循环的父子引用链,但查询可以在任何记录中中断,而不是逻辑上的那些记录。

要解决此问题,首先需要修复查询。你错过了"静态"的条件。 CTE的一部分(在UNION之前)。您需要将此部分中的行限制为叶子(底部 - 顶部方法)或根(上下方法),即没有其他子项(第一种方法)或没有父项(第二种方法)的行。

这样查询就不会中断,并且它不会列出将其作为父级链接的前辈的记录。此外,行不会在结果中多次列出。 然后,您必须将cte加入到原始表中,以检查来自表中的哪些记录未在cte中列出 - 这些将是您正在寻找的行。

答案 1 :(得分:1)

我的想法:禁用递归限制,添加一个跟踪递归级别的列,然后过滤level > 100

  

只是想知道是否存在SQL中其他错误的通用解决方案,例如显示错误的所有记录。

这里没有一般解决方案。查询处理器可以生成各种计划,其中许多计划没有明确的“记录顺序”或发生错误的第一点的概念。当记录通过管道时,它们通常是不完整的,并且与您所写的内容不符。

查询中的跟踪错误是一种常见的请求(想想DML中途失败 - 没有指示错误的位置)。不幸的是,这里没有好的解我最好的建议是避免查询计划中的危险模式。这说起来容易一些。