How to convert recursive CTE to be usable in SQL Server 2000

妖精的绣舞 提交于 2020-01-04 15:58:29

问题


I have a recursive CTE-query like this:

;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;


Would there be any way to realise this without CTE (i.e. for SQL Server 2000)?
Any hints/ideas are appreciated.


回答1:


For SQL 2000, you can create a table-function that mimics your CTE expression, using a temporary table and a WHILE loop to load it.

The main drawback is that you won't benefit from applying WHERE constraints before returning from the function, but it works if the hierarchy table is small. To lessen the amount of data read before the WHERE clauses apply, you can pass parameters to filter (see comment on code):

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;


来源:https://stackoverflow.com/questions/21990957/how-to-convert-recursive-cte-to-be-usable-in-sql-server-2000

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!