Sql server 2008 T-SQL递归选择循环依赖
我的数据库中有自相关的实体a,它们是从另一个实体b引用的,给定一个特定的b实体,我需要得到所有需要的a实体。这些是多对多映射,因此我有一个单独的映射表。我认为带CTE的递归选择是我最好的选择,但我遇到了一个问题: 这说明了我的问题。如果某个用户引入循环引用,我的递归select会突然停止。我一直在绞尽脑汁想办法解决这个问题。应该注意的是,虽然我在小提琴中引入了外键,但实际上我与DBA之间使用的系统并不尊重外键——我引入外键是为了使数据流更加清晰 递归查询,针对那些不想点击小提琴的人:Sql server 2008 T-SQL递归选择循环依赖,sql-server-2008,tsql,recursion,Sql Server 2008,Tsql,Recursion,我的数据库中有自相关的实体a,它们是从另一个实体b引用的,给定一个特定的b实体,我需要得到所有需要的a实体。这些是多对多映射,因此我有一个单独的映射表。我认为带CTE的递归选择是我最好的选择,但我遇到了一个问题: 这说明了我的问题。如果某个用户引入循环引用,我的递归select会突然停止。我一直在绞尽脑汁想办法解决这个问题。应该注意的是,虽然我在小提琴中引入了外键,但实际上我与DBA之间使用的系统并不尊重外键——我引入外键是为了使数据流更加清晰 递归查询,针对那些不想点击小提琴的人: WITH
WITH recur(objID) AS (
SELECT usesObjID
FROM #otherObj
WHERE otherObjID = 1
UNION ALL
SELECT slaveObjID
FROM #objMap
INNER JOIN recur
on #objMap.masterObjID = recur.objID
)SELECT objID from recur
有什么想法吗?此设计未投入生产,因此我可以在某种程度上更改模式,但我不希望依赖于在插入时发现循环引用,除非它可以通过t-SQL完成。可以设置CTE的值,这将防止无限循环,但是您仍然会得到奇怪的结果,因为查询将继续在循环中运行,直到达到最大递归
挑战在于循环涉及多个步骤,因此您不能只检查子循环的直接父循环以确定您是否处于循环中
处理此问题的一种方法是在CTE中添加一个附加列。。。这个新列tree跟踪到目前为止包含的所有ID,并在ID重复时停止
WITH recur(objID, Tree) AS (
SELECT
usesObjID,
CAST(',' + CAST(usesObjID AS VARCHAR) + ',' AS VARCHAR) AS Tree
FROM otherObj
WHERE otherObjID = 1
UNION ALL
SELECT
slaveObjID,
CAST(recur.Tree + CAST(slaveObjID AS VARCHAR) + ',' AS VARCHAR) AS Tree
FROM objMap
INNER JOIN recur
ON objMap.masterObjID = recur.objID
WHERE recur.Tree NOT LIKE '%,' + CAST(slaveObjID AS VARCHAR) + ',%'
)SELECT objID from recur
从未使用过此fxn,但您是否只会在objMap.masterObjID=recur.objID和recur.objID otherobj.usesObjID上说?还是超出了范围?太棒了!如果是从otherObj到Obj的多对多映射,您认为这也会起作用吗?需要另一个映射吗table@FrankieTheKneeMan我认为这也会起作用。基本上,您仍然只需跟踪到目前为止已加入的ID,并在看到重复的ID时停止@FrankieTheKneeMan我认为这取决于你如何使用数据。有时您可能只需要一个ID,其他时候,如果您使用树下的不同路径到达ID,您可能需要两次ID。。。如果你需要的是独特的,那么我就说用它…好吧。非常感谢!我希望我能不止一次地否决你的答案。