SQL Server中类似递归的查询

时间:2011-12-04 00:53:55

标签: sql-server tsql stored-procedures

我试图找出如何在SQL中执行本质上是递归查询的内容。我有两张桌子;

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 

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

1 个答案:

答案 0 :(得分:2)

如果您使用的是SQL Server 2005或更高版本,则可以使用递归CTE (公用表表达式)来执行此操作(有关详细信息,请参阅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分阶段运行:

  • 第一个“run”设置锚点,即执行第一个SELECT并将结果存储在临时结果集中
  • 然后,处理递归:运行第二个选择,基本上选择所有依赖于第一次运行中选择的行的行 - 所有那些像这样链接的行:

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

第二步一遍又一遍地重复,直到不再检索到其他行 - 然后返回结果集。