對於SELECT查詢語句來講,一般狀況下,爲了使T-SQL代碼更加簡潔和可讀,在一個查詢中引用另外的結果集都是經過視圖而不是子查詢來進行分解的.可是,視圖是做爲系統對象存在數據庫中,那對於結果集僅僅須要在存儲過程或是用戶自定義函數中使用一次的時候,使用視圖就顯得有些奢侈了.html
公用表表達式(Common Table Expression)是SQL SERVER 2005版本以後引入的一個特性.CTE能夠看做是一個臨時的結果集,能夠在接下來的一個SELECT,INSERT,UPDATE,DELETE,MERGE語句中被屢次引用。使用公用表達式可讓語句更加清晰簡練.數據庫
除此以外,根據微軟對CTE好處的描述,能夠歸結爲四點:express
公用表達式的定義很是簡單,只包含三部分:服務器
在MSDN中的原型:函數
按照是否遞歸,能夠將公用表(CTE)表達式分爲遞歸公用表表達式和非遞歸公用表表達式.spa
非遞歸公用表表達式(CTE)是查詢結果僅僅一次性返回一個結果集用於外部查詢調用。並不在其定義的語句中調用其自身的CTE3d
非遞歸公用表表達式(CTE)的使用方式和視圖以及子查詢一致htm
好比一個簡單的非遞歸公用表表達式:對象
固然,公用表表達式的好處之一是能夠在接下來一條語句中屢次引用:blog
前面我一直強調「在接下來的一條語句中」,意味着只能接下來一條使用:
因爲CTE只能在接下來一條語句中使用,所以,當須要接下來的一條語句中引用多個CTE時,能夠定義多個,中間用逗號分隔:
遞歸公用表表達式很像派生表(Derived Tables ),指的是在CTE內的語句中調用其自身的CTE.與派生表不一樣的是,CTE能夠在一次定義屢次進行派生遞歸.對於遞歸的概念,是指一個函數或是過程直接或者間接的調用其自身,遞歸的簡單概念圖以下:
遞歸在C語言中實現的一個典型例子是斐波那契數列:
long fib(int n) { if (n==0) return 0; if (n==1) return 1; if (n>1) return fib(n-1)+fib(n-2); }
上面C語言代碼能夠看到,要構成遞歸函數,須要兩部分。第一部分是基礎部分,返回固定值,也就是告訴程序什麼時候開始遞歸。第二部分是循環部分,是函數或過程直接或者間接調用自身進行遞歸.
對於遞歸公用表達式來講,實現原理也是相同的,一樣須要在語句中定義兩部分:
在SQL這兩部分經過UNION ALL鏈接結果集進行返回:
好比:在AdventureWork中,我想知道每一個員工所處的層級,0是最高級
這麼複雜的查詢經過遞歸CTE變得如此優雅和簡潔.這也是CTE最強大的地方.
固然,越強大的力量,就須要被約束.若是使用不當的話,遞歸CTE可能會出現無限遞歸。從而大量消耗SQL Server的服務器資源.所以,SQL Server提供了OPTION選項,能夠設定最大的遞歸次數:
仍是上面那個語句,限制了遞歸次數:
所提示的消息:
這個最大遞歸次數每每是根據數據所表明的具體業務相關的,好比這裏,假設公司層級最多隻有2層.
CTE是一種十分優雅的存在。CTE所帶來最大的好處是代碼可讀性的提高,這是良好代碼的必須品質之一。使用遞歸CTE能夠更加輕鬆愉快的用優雅簡潔的方式實現複雜的查詢。