2011-12-04 70 views
0

我想弄清楚如何执行本质上是SQL中的递归查询。我有两张桌子;在SQL Server中的递归式查询

TABLE Object(
id INT NOT NULL PRIMARY KEY 
) 

TABLE ObjectDependency(
object_id INT, 
dependency_id INT, 
FOREIGN KEY(object_id)  REFERENCES Object(id) 
FOREIGN KEY(dependency_id) REFERENCES Object(id) 
) 

我想写一个存储过程,将对象ID和吐出的所有对象依赖关系的(这样的事情,而且还找到任何依赖的依赖。

SELECT id, ObjectDependency.id FROM Object 
JOIN ObjectDependency ON object_id = id 

该系统设置的方式是没有周期性的依赖关系,但是我对如何将所有结果循环到一个存储过程的方式感到迷茫。

+0

如果只有您有权访问递归CTE ... ;-) – 2011-12-04 00:57:41

+0

为此,针对不同数据库产品(Oracle/Mysql/PostgreSQL/MS SQL/...)有不同的解决方案。你在使用哪一个? –

+0

我正在使用MS SQL。 – user308926

回答

2

如果您使用的是SQL Server 2005或更新的版本,那么您可以使用递归CTE 01的(公用表表达式)来完成此操作(有关更多详细信息,请参阅MSDN Books Online docs)。

基本上,它是一个“内联视图” - 仅存在于下一个语句的视图。 CTE的一个版本专门用于处理递归场景。

它看起来是这样的:

CREATE PROCEDURE dbo.RecurseObjects @ObjectID INT 
AS BEGIN 
    WITH ObjectCTE AS 
    (
     -- set the anchor - select the object defined 
     SELECT o.id AS 'ID', CAST(NULL AS INT) AS 'ParentID', 1 AS 'Level' 
     FROM dbo.Object o 
     WHERE o.id = @ObjectID 

     -- add recursion 
     UNION ALL 

     SELECT o2.id AS 'ID', cte.id AS 'ParentID', cte.Level + 1 AS 'Level' 
     FROM dbo.Object o2 
     INNER JOIN dbo.ObjectDependency od ON od.dependency_id = o2.id 
     INNER JOIN ObjectCTE cte ON cte.id = od.object_id 
) 
    SELECT * 
    FROM ObjectCTE 
END 

所以这个递归CTE分阶段运行:

  • 第一“运行”设置锚,也就是第一SELECT被执行,结果存储在临时结果集中
  • 然后处理递归:运行第二个select,基本上从第一次运行中选择的行中选择所有依赖的行 - 全部th被链接这样OSE:

    object.id --> objectdepedency.dependecy_id 
           objectdepedency.object_id --> "parent" object.id 
    

该第二步骤反复重复,直到没有更多的额外行被检索 - 然后被返回的结果集。