T SQL 公用表表示式 CTE

2021-09-07 05:40:50 字數 3930 閱讀 4777

在編寫t-sql**時,往往需要臨時儲存某些結果集。前面我們已經廣泛使用和介紹了兩種臨時儲存結果集的方法:臨時表和表變數。除此之外,還可以使用公用表表示式的方法。公用表表示式(common table expression)是sql server2005版本的引入的乙個特性。cte可以看組是乙個臨時的結果集,可以再接下來來的乙個select,insert,update,delete,merge語句中多次引用。使用公用表示式cte可以讓語句更加清晰簡練。與公用表示式作用類似的還有臨時表和表變數。下面給出三種方法的對比。

1、3種方法比較

(一)、臨時表:需要在臨時資料庫tempdb中通過i/o操作來建立表結構,一旦使用者推出sql server環境則自動被刪除。

(二)、表變數:在記憶體中以表結構的形式存在,其定義與變數一致,其使用與表類似,不需要產生i/o。

(三)、公用表表示式:common table expression,定義在記憶體中儲存的臨時儲存結果集物件,不產生i/o,不需要按照表變數這樣定義,使用方法和表類似。可以自己引用,也可以再查詢中被多次引用。

2、with as的含義

with as-做子查詢部分(subquery factoring)。

它用於定義乙個sql片段,該片段會被是整個sql語句所用到。如果with as所以定的表名被呼叫兩次以上,則優化器會自動將with as所獲取的資料放入臨時表裡,如果只是被呼叫一次,則不會。可以通過materialize將with as短語裡的資料強制放入全域性臨時表裡。

with as可以被緊跟著的一條sql語句所使用多次,但不能被緊跟著的多條sql語句使用。

with b as 

( select * from *** where id > 5

)select * from b

3、cte的定義cte的定義語法如下,主要包括3個部分。

(一)、expression_name:cte表示式的名稱。

(二)、column_name:列名列表。

(三)、cte_query_definition:定義cte結果集的select查詢語句

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

as(

cte_query_definition

)

根據微軟對cte好處的描述,可以歸結為四點:

按照是否遞迴,可以將公用表(cte)表示式分為遞迴公用表表示式和非遞迴公用表表示式.

非遞迴公用表表示式(cte):

非遞迴公用表表示式(cte)是查詢結果僅僅一次性返回乙個結果集用於外部查詢呼叫。並不在其定義的語句中呼叫其自身的cte。

非遞迴公用表表示式(cte)的使用方式和檢視以及子查詢一致。

比如乙個簡單的非遞迴公用表表示式:

with cte_testas(

select * from person_1

)select * from cte_test

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

with cte_test

as(   select * from person_1

)  select * from cte_test as a  --第一次引用

inner join cte_test as b    --第二次引用

on a.id = b.id

order by a.id desc

雖然以上引用了多次,但是只是一條語句,所以可以正常執行。

如果多條語句引用,如下面這樣,是會報錯的。

with cte_test

as(   select * from person_1

)  select * from cte_test

select * from cte_test

輸出結果如下:

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

with cte_test1as(

select * from person_1

),cte_test2as(

select * from person_2

)select * from cte_test1

union

select * from cte_test2

結果如下:

遞迴公用表表示式(cte):

對於遞迴公用表示式來說,只需要在語句中定義兩部分:

先建一張表欄目表如下,欄目id,欄目名稱,欄目的父欄目。

現在使用cte查詢其每個欄目是第幾層欄目的**如下:

with col_cte(id,name,parentid,tlevel )as(

--基本語句

select id,name,parentid,0 as tlevel from col

where parentid = 0

union all

--遞迴語句

select c.id,c.name,c.parentid,ce.tlevel+1 as tlevel from col as c

inner join col_cte as ce   --遞迴呼叫

on c.parentid = ce.id

)select * from col_cte

輸出結果如下:

0表示頂級欄目。1就是1級欄目。語法非常優雅。就乙個select * fron col_cte。這正是cte強大的地方,但是,這要有約束,否則如果無限制遞迴可以會消耗掉非常多的系統資源。下面來看看如何限制遞迴的最大次數。

如將上面的查詢語法改為:

with col_cte(id,name,parentid,tlevel )as(

--基本語句

select id,name,parentid,0 as tlevel from col

where parentid = 0

union all

--遞迴語句

select c.id,c.name,c.parentid,ce.tlevel+1 as tlevel from col as c

inner join col_cte as ce

on c.parentid = ce.id

)select * from col_cte

option(maxrecursion 2)  --指定最大遞迴次數為2

我們知道在上面的查詢中,要查到天河區新聞最少要遞迴3次,但是現在只遞迴2次,執行是什麼結果呢?

提示資訊如下:

訊息 530,級別 16,狀態 1,第 1 行

語句被終止。完成執行語句前已用完最大遞迴 2。

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

T SQL 公用表表示式 CTE

在編寫t sql 時,往往需要臨時儲存某些結果集。前面我們已經廣泛使用和介紹了兩種臨時儲存結果集的方法 臨時表和表變數。除此之外,還可以使用公用表表示式的方法。公用表表示式 common table expression 是sql server2005版本的引入的乙個特性。cte可以看組是乙個臨時的...

公用表表示式CTE

公用表表示式cte表面上和派生表非常相似,看起來只是語義上的區別。但和派生表比較起來,cte具有幾個優勢 第一,如果須要在乙個cte中引用另乙個cte,不需要像派生表那樣巢狀,相反,只要簡單地在同乙個with子句中定義多個cte,並用逗號把它們分隔開。每個cte可以引用在它前面定義的所有cte。而外...

公用表表示式 CTE

在編寫t sql 時,往往需要臨時儲存某些結果集。前面我們已經廣泛使用和介紹了兩種臨時儲存結果集的方法 臨時表和表變數。除此之外,還可以使用公用表表示式的方法。公用表表示式 common table expression 是sql server2005版本的引入的乙個特性。cte可以看組是乙個臨時的...