2014-02-24 43 views
2

我有一個遞歸CTE查詢是這樣的:如何遞歸CTE轉換成SQL Server中使用的2000

;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 )?
任何提示/想法表示讚賞。

+7

熱膨脹係數是「標準SQL」。 SQL Server 2000遠遠落後於曲線,並且不再受MS支持,所以在升級服務器上花費的時間會更多。 –

+0

@Damien_The_Unbeliever你當然是對的。這不像我仍然使用SQL Server 2000;它更多用於學習目的 – seph

+0

對於標準SQL,您需要將語句終止符';'放在語句的末尾,並將'recursive'關鍵字添加到'with'部分。 –

回答

2

對於SQL 2000,您可以使用臨時表和WHILE循環加載它來創建一個模擬CTE表達式的表函數。

主要缺點是在從函數返回之前,您不會受益於應用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;