在使用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
這樣的話,就能夠控制遞歸次數了。這個小技巧仍是挺實用的,分享給你們循環