如何将递归CTE转换为可在SQL Server 2000中使用

时间:2014-02-24 14:43:55

标签: sql sql-server recursion

我有一个这样的递归CTE查询:

;WITH    cte
      AS ( SELECT   e.entryID ,
                    e.bOpen ,
                    e.nextEntryID ,
                    e.entryID AS OriginalentryID
           FROM     entries e
           WHERE    e.bOpen = 1
                    AND e.nextEntryID IS NOT NULL

           UNION ALL

           SELECT   e.entryID ,
                    e.bOpen ,
                    e.nextEntryID ,
                    c.OriginalentryID
           FROM     cte c
                    INNER JOIN entries e ON e.entryID = c.nextEntryID
         )
SELECT  c.entryID ,
        c.OriginalentryID
FROM    cte c
WHERE   bOpen = 0;


如果没有CTE(即对于SQL Server 2000),是否有任何方法可以实现这一点? 任何提示/想法都表示赞赏。

1 个答案:

答案 0 :(得分:2)

对于SQL 2000,您可以创建一个模拟CTE表达式的表函数,使用临时表和WHILE循环来加载它。

主要缺点是,在从函数返回之前,您不会受益于应用WHERE约束,但如果层次结构表很小,它将起作用。要在WHERE子句应用之前减少读取的数据量,可以将参数传递给过滤器(请参阅代码注释):

CREATE FUNCTION dbo.FnGetEntriesByRoot (@rootId AS BIGINT)
RETURNS @result TABLE (
  entryID           BIGINT PRIMARY KEY,
  bOpen             BIT,
  nextEntryID       BIGINT,
  OriginalentryID   BIGINT
)
AS BEGIN

  -- insert the "root" element
  INSERT @result(entryID, bOpen, nextEntryID, OriginalentryID)
  SELECT e.entryID, e.bOpen, e.nextEntryID, e.entryID
  FROM entries e
  WHERE e.bOpen = 1
  AND (e.entryID = @rootId OR @rootId IS NULL) -- (1) filter condition!
  AND e.nextEntryID IS NOT NULL;

  -- while new items are found, insert into the result table
  WHILE (@@ROWCOUNT > 0) BEGIN
    INSERT @result(entryID, bOpen, nextEntryID, OriginalentryID)
    SELECT e.entryID, e.bOpen, e.nextEntryID, c.OriginalentryID
    FROM @result  c
    JOIN entries  e ON (e.entryID = c.nextEntryID)
    WHERE e.entryID NOT IN (SELECT entryID FROM @result)
  END

  RETURN;
END;

SELECT c.entryID, c.OriginalentryID
FROM dbo.FnGetEntriesByRoot(NULL) c
WHERE c.bOpen = 0;