sql server中的cte

從SQL Server 2005開始,提供了CTE(Common Table Expression,公用表表達式)的語法支持。html

CTE是定義在SELECT、INSERT、UPDATE或DELETE語句中的臨時命名的結果集,同時CTE也能夠用在視圖的定義中。數據庫

在CTE中能夠包括對自身的引用,所以這種表達式也被稱爲遞歸CTE。express

CTE的優勢app

公用表表達式提供的功能其實和視圖差很少,可是它不像視圖同樣把SQL語句保存在咱們的數據庫裏面。ui

微軟官方給出的使用CTE的優點:spa

1.能夠編寫一個遞歸查詢。code

2.要使用一個相似視圖的功能,可是又不想把這個查詢SQL語句的定義保存到數據庫中。htm

3.要引用一個返回數據的SQL語句屢次,只須要定義一次。blog

使用CTE能夠把複雜的SQL語句按照邏輯分紅簡單獨立的幾個公用表表達式(CTE),這樣的最大優點就是可以提升SQL語句的可讀性和可維護性。遞歸

總結就是,CTE主要能夠用於樹結構的遞歸和簡化SQL語句,增長可讀性和可維護性。

CTE的使用場景

因爲業務須要,咱們常常會寫一些比較複雜的SQL語句,裏面可能會包含不少的JOIN或子查詢,要維護和理清這種N多個表的JOIN關係是一件很是頭疼的事情,而使用CTE就可使維護和理解複雜的SQL語句變得簡單一些。

在開發的時候使用子查詢,通常是這種狀況:須要從一個複雜的子查詢,甚至多級子查詢嵌套。在這種狀況下,在整個SQL語句裏面,不管你是直接寫SQL語句仍是把這段SQL語句包裝成子查詢而後用別名來訪問,當業務需求愈來愈變得複雜,你可能隨時須要修改這個長且複雜的SQL語句段,而維護這種複雜的、可讀性差的SQL語句簡直是噩夢。

有了CTE只有,咱們就可使用CTE來定義一個SQL語句,而且爲這個SQL語句執行後返回的結果集定義一個別名,接下來就能夠經過這個別名來引用這些預先執行返回的數據集,就像使用普通的表同樣。

CTE的語法

一個公用表表達式主要包含三個主要部分:

1.CET名稱(WITH後面,列名列以前)。

2.列名列(可選)。

3.CET查詢語句主體(AS後面括起來的內容)。

with expression_name (column_name, …) as ( -- cte_query_definition cte查詢語句定義
)

要注意的是,若是要定義多個表達式,須要用逗號分隔。

使用CTE進行屢次查詢

CTE是能夠在跟隨其後的查詢中屢次引用的。

with tmp(id) as ( select id from users where name like '楊%'; ) select * from tmp; select * from orders where userId in (select id from tmp);

使用CTE遞歸查詢樹形記錄(向上查詢父節點或向下查詢子節點)

CTE有一個特性就是它是支持遞歸的,即在CTE的查詢語句主體中引用自身。這一特性經常被用在查詢樹形記錄。

with subqry(id, pid, name) as ( select cb.id, cb.pid, cb.namefrom cb where cb.id = '001001001'
  
        union all
  
        select cb.id, cb.pid, cb.namefrom cb, subqry where cb.id = subqry.pid ) select distinct *
from subqry
with subqry(id, pid, name) as ( select cb.id, cb.pid, cb.name from cb where cb.id = '001'
  
        union all
  
        select cb.id, cb.pid, cb.name from cb, subqry where cb.pid = subqry.id ) select distinct *
from subqry

使用CTE的注意事項

1.CTE後面必須緊跟着使用CTE的SQL語句,好比SELECT、INSERT和UPDATE等,不然CTE將失效(直接報錯)。

with tmp(id) as ( select id from users where favor = '牛奶'; ) select 1; select * from tmp;

像上面的語句就會報【定義了公用表表達式,但沒有使用】的錯。

2.CTE後面也能夠跟其餘的CTE,可是隻能使用一個WITH,多個CTE中間用逗號【,】隔開。

with milk(id) as ( select id from users where favor = '牛奶'; ), apple(id) as ( select id from users where favor = '蘋果'; ) select id from milk, apple where milk.id = apple.id

3.若是CTE表達式名稱與某個實體表或者視圖重名,則緊跟在該CTE後面的SQL語句使用的仍然是CTE。

要注意的是,後面再使用該同名就是使用實體表或視圖了。

4.CTE能夠引用自身,也能夠引用在同一個WITH子句中預先定義的CTE,可是不容許前向引用(定義前使用)。

5.不能在CTE_QUERY_DEFINITION(CTE查詢語句定義)中使用如下子句:

(1)COMPUTE或COMPUTE BY
(2)ORDER BY(除非指定了TOP 子句)
(3)INTO
(4)帶有查詢提示的OPTION 子句
(5)FOR XML
(6)FOR BROWSE

6.若是將CTE用於批處理的一部分的語句中,那麼在它以前的語句必須以分號結尾。

declare @id int
set @id = 0; -- 這裏必須以分號結尾
;with tmp(name) as ( -- 在with前加上分號避免出錯
    select name from users where unrequitedLove = '靜靜'; ) select * from tmp;

固然了,一個良好的習慣(技巧)是在寫CTE的時候通通在WITH前加上分號【;】,這樣就能避免出錯,好比上面的語句。

總結

若是常常寫查詢的話,好比一些統計分析或製做報表,CTE是會常用到的,由於使用起來十分方便,也幾乎不會有什麼反作用,在必定程度上可以提升開發和維護的效率。另外,其遞歸屬性在樹形記錄的查詢中的應用十分普遍,是一個要好好掌握的語法。

 

"我仍是很喜歡你,像樵人薄暮,倦鳥歸棲。"

原文出處:https://www.cnblogs.com/yanggb/p/11165276.html

相關文章
相關標籤/搜索