CTE遞歸 MAXRECURSION 遇到的問題

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

當面對第一種狀況,層數超過了100,比方說用於生成數列或者日期的時候,講 maxrecursion 設置爲 -1就能夠解決,這個也不是問題。可是若是是死循環的話呢,就須要檢查本身數據和查詢語句的邏輯了。spa

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

先給答案,是不行的,而後上例子,顯而易見,這裏確定是一個死循環,而後返回結果是醬紙的。code

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

 

顯示出來第一層,而後就是一直遞歸最後一條數據。能夠看出來,並非每一條數據手牽手遞歸一層,而後又手牽手遞歸一層的效果,而是先遊標遞歸完最後一條,而後反推回來最上面一條的。blog

在這個緣由,因此你看到這個簡單的例子裏面,就不存在遞歸A~F的狀況。遞歸

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

可是若是要控制遞歸次數的話,能夠作一個小改動,就能夠控制遞歸次數class

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

 

這樣的話,就能夠控制遞歸次數了。這個小技巧仍是挺實用的,分享給你們循環

相關文章
相關標籤/搜索