Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何在CTE中查找父/子表之间的循环引用_Sql Server_Sql Server 2012_Common Table Expression - Fatal编程技术网

Sql server 如何在CTE中查找父/子表之间的循环引用

Sql server 如何在CTE中查找父/子表之间的循环引用,sql-server,sql-server-2012,common-table-expression,Sql Server,Sql Server 2012,Common Table Expression,我有一个CTE来显示两个表(父表和子表)上的依赖关系树。 存在导致循环依赖的数据问题,导致抛出最大递归级别错误。 i、 e 这些表中有数千行。如何编写查询以识别有问题的引用?或者有没有一种方法可以设置最大递归级别,一旦命中就停止CTE,而不是抛出错误…然后我可以查看结果并确定问题的子项 WITH Recursive_CTE AS ( SELECT ItemId, CAST(ItemDescription AS varchar(100))

我有一个CTE来显示两个表(父表和子表)上的依赖关系树。 存在导致循环依赖的数据问题,导致抛出最大递归级别错误。 i、 e

这些表中有数千行。如何编写查询以识别有问题的引用?或者有没有一种方法可以设置最大递归级别,一旦命中就停止CTE,而不是抛出错误…然后我可以查看结果并确定问题的子项

WITH Recursive_CTE AS 
(
    SELECT        
        ItemId, 
        CAST(ItemDescription AS varchar(100)) AS ItemDescription, 
        Qty, 
        CAST(ParentItemId AS SmallInt) AS ParentItemId, 
        CAST(ItemId AS varchar(100)) AS ParentGroupItemId, 
        CAST('   -' AS varchar(100)) AS LVL, 
        CAST(ItemId AS varchar(100)) AS HierarchyItem, 
        CAST(SKU AS varchar(100)) AS HierarchySKU, 
        CAST(ItemDescription AS varchar(100)) AS HierarchyName, 
        0 AS RecursionLevel
    FROM dbo.vw_BOM AS child
    WHERE (ParentItemId = 0) 
    --and ItemId = @BOMHeaderItemId

    UNION ALL

    SELECT        
        child.ItemId, 
        CAST(parent.LVL + child.ItemDescription AS varchar(100)) AS ItemDescription, 
        child.Qty, 
        CAST(child.ParentItemId AS SmallInt) AS ParentItemId, 
        parent.ParentGroupItemId, 
        CAST('   -' + parent.LVL AS varchar(100)) AS LVL, 
        CAST(parent.HierarchyItem + ':' + CAST(child.ItemId AS varchar(100)) AS varchar(100)) AS HierarchyItem,
        CAST(parent.HierarchySKU + ':' + CAST(child.SKU AS varchar(100)) AS varchar(100)) AS HierarchySKU, 
        CAST(parent.HierarchyName + '/' + CAST(child.ItemDescription AS varchar(100)) AS varchar(100)) AS HierarchyName, 
        parent.RecursionLevel + 1 AS RecursionLevel
    FROM Recursive_CTE AS parent INNER JOIN
            dbo.vw_BOM AS child ON child.ParentItemId = parent.ItemId
)

SELECT        
    Recursive_CTE_1.RecursionLevel, 
    Recursive_CTE_1.ParentGroupItemId, 
    Recursive_CTE_1.ParentItemId, 
    Recursive_CTE_1.ItemId, 
    Recursive_CTE_1.Qty, 
    DATALENGTH(Recursive_CTE_1.LVL) AS LVLLength,
    Recursive_CTE_1.ItemDescription, 
    item.SKU, 
    item.OnHandQty, 
    item.AllocQty, 
    item.AvailableQty, 
    item.ToBeReceivedQty, 
    item.AvailableWFutureQty,   
    Recursive_CTE_1.HierarchyItem, 
    Recursive_CTE_1.HierarchySKU, 
    Recursive_CTE_1.HierarchyName
FROM Recursive_CTE AS Recursive_CTE_1 INNER JOIN
        dbo.vw_ItemInventorySummary AS item ON Recursive_CTE_1.ItemId = item.Id
ORDER BY Recursive_CTE_1.HierarchySKU
option (maxrecursion 200)
视图vw_BOM

SELECT        dbo.BillOfMaterialHeader.Id AS Id, dbo.BillOfMaterialHeader.ItemId AS ItemId, 0 AS ParentItemId, FGItems.SKU AS SKU, FGItems.SKU + N': ' + FGItems.ShortDescription AS ItemDescription, 
                         dbo.BillOfMaterialHeader.Quantity AS Qty
FROM            dbo.BillOfMaterialHeader INNER JOIN
                         dbo.Items AS FGItems ON dbo.BillOfMaterialHeader.ItemId = FGItems.Id
UNION ALL
SELECT        dbo.BillOfMaterialDetail.Id AS Id, dbo.BillOfMaterialDetail.ItemId AS ItemId, BOMHdr.ItemId AS ParentItemId, RMItems.SKU AS SKU, RMItems.SKU + N': ' + RMItems.ShortDescription AS ItemDescription, 
                         dbo.BillOfMaterialDetail.Quantity AS Qty
FROM            dbo.Items AS RMItems INNER JOIN
                         dbo.BillOfMaterialDetail ON RMItems.Id = dbo.BillOfMaterialDetail.ItemId INNER JOIN
                         dbo.BillOfMaterialHeader BOMHdr ON dbo.BillOfMaterialDetail.BillOfMaterialHeaderId = BOMHdr.Id
更新

Tab的回答为我指明了正确的方向。我在vw_BOM中使用了扁平化的父子表,然后根据选项卡的答案将其连接到自身,这表明在父表和子表中有6个项目具有相同的项目Id。 像这样:


简单自连接应该做到这一点:

SELECT * FROM MyTable t1
INNER JOIN MyTable t2
  ON t1.Parent=t2.Child
  AND t1.Child=t2.Parent 

简单自连接应该做到这一点:

SELECT * FROM MyTable t1
INNER JOIN MyTable t2
  ON t1.Parent=t2.Child
  AND t1.Child=t2.Parent 

您的CTE已经有一个连接了ItemID路径的层次结构。用它来确定是否已经看到了该项目,怎么样

将新列添加到CTE的锚定部分,
HasCycle=Convert(位,0)

然后在CTE的递归部分,在
WHERE
子句中添加列和条件,如下所示:

...
UNION ALL
SELECT
   ... other columns,
   HasCycle = Convert(bit,
      CASE
          WHEN ':' + parent.HierarchyItem + ':' LIKE
             '%:' + Convert(varchar(100), child.ItemID) + ':%'
          THEN 1
          ELSE 0
      END)
FROM
   ...
WHERE
   ...
   AND parent.HasCycle = 0 --terminate after cycle is found
;

然后,您可以从递归CTE
中进行选择,其中HasCycle=1
,并在
层次项目中查看开始循环的所有行及其向上的确切路径。用它来确定是否已经看到了该项目,怎么样

将新列添加到CTE的锚定部分,
HasCycle=Convert(位,0)

然后在CTE的递归部分,在
WHERE
子句中添加列和条件,如下所示:

...
UNION ALL
SELECT
   ... other columns,
   HasCycle = Convert(bit,
      CASE
          WHEN ':' + parent.HierarchyItem + ':' LIKE
             '%:' + Convert(varchar(100), child.ItemID) + ':%'
          THEN 1
          ELSE 0
      END)
FROM
   ...
WHERE
   ...
   AND parent.HasCycle = 0 --terminate after cycle is found
;


然后,您可以从递归CTE
中进行选择,其中HasCycle=1
,并在
层次项目中查看开始一个循环的所有行及其向上的确切路径

我以前见过这些问题,并尝试一次添加一个级别的项目,忽略以前看到的问题。

我以前看到过这些问题,每次只添加一个级别的项,忽略以前看到的项。

可以发布表结构和当前查询吗?我无法想象你是如何从两个表的父子结构中得到最大递归错误的。@TabAlleman-Tab,我添加了表结构。让我知道这是否有意义。@ChadRichardson,当你看到这个错误时,实际上你也可以看到选择的结果,你最终会看到什么行给了你问题。@GiorgiNakeuri谢谢Giorgi,但在SSMS中这不是我的问题,结果选项卡没有任何行,消息选项卡显示最大递归错误。@ChadRichardson,可以显示查询吗?可以发布表结构和当前查询吗?我无法想象你是如何从两个表的父子结构中得到最大递归错误的。@TabAlleman-Tab,我添加了表结构。让我知道这是否有意义。@ChadRichardson,当你看到这个错误时,实际上你也可以看到选择的结果,你最终会看到什么行给了你问题。@GiorgiNakeuri谢谢Giorgi,但在SSMS中这不是我的问题,结果选项卡没有任何行,消息选项卡显示最大递归错误。@ChadRichardson,你能显示查询吗?你不能这样做。循环引用可能通过几个级别出现。没错,最初的问题让我相信只有两个级别。但它确实帮助我确定了一些问题,其中父表及其直接子表具有相同的ItemId。但可能还有其他更复杂的循环引用。你刚刚保存了我的星期五:)你不能这样做。循环引用可能通过几个级别出现。没错,最初的问题让我相信只有两个级别。但它确实帮助我确定了一些问题,其中父表及其直接子表具有相同的ItemId。但可能还有其他更复杂的循环引用。您刚刚保存了我的星期五:)