CTE遞歸 MAXRECURSION 遇到的問題


在使用Sql Server的時候,當需要遞歸的時候很多時候就會想到使用CTE。但是當遞歸層數比較多,超過了100層,或者是一個遞歸死循環的時候。執行就會爆遞歸次數已到,最多100的錯誤。

當面對第一種情況,層數超過了100,比方說用於生成數列或者日期的時候,講 maxrecursion 設置為 -1就可以解決,這個也不是問題。但是如果是死循環的話呢,就需要檢查自己數據和查詢語句的邏輯了。

這里我要說的是,假如我們在查詢的時候手動設置 maxrecursion  的時候,能不能避免死循環,只循環到某一層呢?

先給答案,是不行的,然后上例子,顯而易見,這里肯定是一個死循環,然后返回結果是醬紙的。

IF OBJECT_ID('tempdb..#ID') IS NOT NULL
    DROP TABLE #ID

CREATE TABLE #ID (ID INT,vname VARCHAR(50))

INSERT INTO #ID
        ( ID, vname )
VALUES  ( 1, 'A'),(2,'B'),(3,'B'),(4,'B'),(5,'B'),(6,'B'),(7,'B')

;WITH CTE AS
(
    SELECT * FROM #ID
    UNION ALL
    SELECT ID+1,CTE.vname
        FROM CTE 
)

SELECT * FROM CTE

 

顯示出來第一層,然后就是一直遞歸最后一條數據。可以看出來,並不是每一條數據手牽手遞歸一層,然后又手牽手遞歸一層的效果,而是先游標遞歸完最后一條,然后反推回來最上面一條的。

在這個原因,所以你看到這個簡單的例子里面,就不存在遞歸A~F的情況。

好,然后回答前面的問題,使用 maxrecursion 的值來控制遞歸次數是不可取的,唯一有用的地方就是減少了遞歸次數,有效減少數據庫的開銷。

但是如果要控制遞歸次數的話,可以做一個小改動,就可以控制遞歸次數

IF OBJECT_ID('tempdb..#ID') IS NOT NULL
    DROP TABLE #ID

CREATE TABLE #ID (ID INT,vname VARCHAR(50))

INSERT INTO #ID
        ( ID, vname )
VALUES  ( 1, 'A'),(2,'B'),(3,'C'),(4,'D'),(5,'E'),(6,'F'),(7,'G')

;WITH CTE AS
(
    SELECT *,1 AS Lv FROM #ID
    UNION ALL
    SELECT ID+1,CTE.vname,Lv+1
        FROM CTE 
        WHERE CTE.Lv < 3
)

SELECT * FROM CTE

 

這樣的話,就可以控制遞歸次數了。這個小技巧還是挺實用的,分享給大家


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM