T-SQL查詢進階--詳解公用表表達式(CTE)

簡介

     對於SELECT查詢語句來說,通常情況下,爲了使T-SQL代碼更加簡潔和可讀,在一個查詢中引用另外的結果集都是通過視圖而不是子查詢來進行分解的.但是,視圖是作爲系統對象存在數據庫中,那對於結果集僅僅需要在存儲過程或是用戶自定義函數中使用一次的時候,使用視圖就顯得有些奢侈了.

    公用表表達式(Common Table Expression)是SQL SERVER 2005版本之後引入的一個特性.CTE可以看作是一個臨時的結果集,可以在接下來的一個SELECT,INSERT,UPDATE,DELETE,MERGE語句中被多次引用。使用公用表達式可以讓語句更加清晰簡練.

     除此之外,根據微軟對CTE好處的描述,可以歸結爲四點:

  •      可以定義遞歸公用表表達式(CTE)
  •      當不需要將結果集作爲視圖被多個地方引用時,CTE可以使其更加簡潔
  •     GROUP BY語句可以直接作用於子查詢所得的標量列
  •     可以在一個語句中多次引用公用表表達式(CTE)

 

公用表表達式(CTE)的定義

    公用表達式的定義非常簡單,只包含三部分:

  1.   公用表表達式的名字(在WITH之後)
  2.   所涉及的列名(可選)
  3.   一個SELECT語句(緊跟AS之後)

    在MSDN中的原型:

WITH expression_name [ ( column_name [,...n] ) ] 

AS 

( CTE_query_definition ) 

 

   按照是否遞歸,可以將公用表(CTE)表達式分爲遞歸公用表表達式和非遞歸公用表表達式.

 

非遞歸公用表表達式(CTE)

   非遞歸公用表表達式(CTE)是查詢結果僅僅一次性返回一個結果集用於外部查詢調用。並不在其定義的語句中調用其自身的CTE

   非遞歸公用表表達式(CTE)的使用方式和視圖以及子查詢一致

   比如一個簡單的非遞歸公用表表達式:

   1

 

   當然,公用表表達式的好處之一是可以在接下來一條語句中多次引用:

 

   2

 

   前面我一直強調“在接下來的一條語句中”,意味着只能接下來一條使用:

   3

 

   由於CTE只能在接下來一條語句中使用,因此,當需要接下來的一條語句中引用多個CTE時,可以定義多個,中間用逗號分隔:

   4

 

遞歸公用表表達式(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是最高級

   5

  

   這麼複雜的查詢通過遞歸CTE變得如此優雅和簡潔.這也是CTE最強大的地方.

   當然,越強大的力量,就需要被約束.如果使用不當的話,遞歸CTE可能會出現無限遞歸。從而大量消耗SQL Server的服務器資源.因此,SQL Server提供了OPTION選項,可以設定最大的遞歸次數:

   還是上面那個語句,限制了遞歸次數:

   6

   所提示的消息:

   7

 

   這個最大遞歸次數往往是根據數據所代表的具體業務相關的,比如這裏,假設公司層級最多隻有2層.

 

總結 

    CTE是一種十分優雅的存在。CTE所帶來最大的好處是代碼可讀性的提升,這是良好代碼的必須品質之一。使用遞歸CTE可以更加輕鬆愉快的用優雅簡潔的方式實現複雜的查詢。



文章出自:http://www.cnblogs.com/CareySon/archive/2011/12/12/2284740.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章