您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“SQL Server怎么使用T-SQL公用表表達式”,內容詳細,步驟清晰,細節處理妥當,希望這篇“SQL Server怎么使用T-SQL公用表表達式”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
在編寫T-SQL代碼時,往往需要臨時存儲某些結果集。前面我們已經廣泛使用和介紹了兩種臨時存儲結果集的方法:臨時表和表變量。除此之外,還可以使用公用表表達式的方法。
公用表表達式(Common Table Expression)是SQL Server2005版本的引入的一個特性。CTE可以看組是一個臨時的結果集,可以再接下來來的一個SELECT,INSERT,UPDATE,DELETE,MERGE語句中多次引用。
使用公用表達式CTE可以讓語句更加清晰簡練。與公用表達式作用類似的還有臨時表和表變量。下面給出三種方法的對比。
臨時表#:需要在臨時數據庫TempDB中通過I/O操作來創建表結構,一旦用戶退出SQL Server環境則自動被刪除。
表變量@:在內存中以表結構的形式存在,其定義與變量一致,其使用與表類似,不需要產生I/O。
公用表表達式with as:定義在內存中保存的臨時存儲結果集對象,不產生I/O,不需要按照表變量這樣定義,使用方法和表類似。可以自己引用,也可以再查詢中被多次引用。
根據微軟對CTE好處的描述,可以歸結為四點:
可以定義遞歸公用表表達式(CTE)
當不需要將結果集作為視圖被多個地方引用時,CTE可以使其更加簡潔
GROUP BY 語句可以直接作用于子查詢所得的標量列
可以在一個語句中多次引用公用表表達式(CTE)
WITH AS-做子查詢部分(subquery factoring)。
它用于定義一個SQL片段,該片段會被是整個SQL語句所用到。如果WITH AS所以定的表名被調用兩次以上,則優化器會自動將WITH AS所獲取的數據放入臨時表里,如果只是被調用一次,則不會。
可以通過materialize將WITH AS短語里的數據強制放入全局臨時表里。
WITH AS可以被緊跟著的一條SQL語句所使用多次,但不能被緊跟著的多條SQL語句使用。
WITH B AS ( SELECT * FROM xxx WHERE Id > 5 ) SELECT * FROM B
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)的使用方式和視圖以及子查詢一致。
比如一個簡單的非遞歸公用表表達式:
WITH CTE_Test AS ( 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_Test1 as (select * from Person_1), CTE_Test2 as (select * from Person_2) select * from CTE_Test1 union select * from CTE_Test2;
結果如下:
對于遞歸公用表達式來說,只需要在語句中定義兩部分:
基本語句
遞歸語句
先建一張表欄目表如下,欄目Id,欄目名稱,欄目的父欄目。
現在使用CTE查詢其每個欄目是第幾層欄目的代碼如下:
declare @table1 table(id int, Name varchar(10), ParentId int); insert into @table1(id, Name, ParentId) values(1, '國內新聞', 0), (2, '廣東新聞', 1), (3, '廣州新聞', 2), (4, '天河新聞', 3), (5, '山東新聞', 1), (5, '青島新聞', 5); select * from @table1; with COL_CTE(Id, Name, ParentId, tLevel) as ( --基本語句 select id, Name, ParentId, 0 as tLevel from @table1 where ParentId=0 union all --遞歸語句 select c.id, c.Name, c.ParentId, ce.tLevel+1 as tLevel from @table1 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 @table1 WHERE ParentId = 0 UNION ALL --遞歸語句 SELECT c.Id,c.Name,c.ParentId,ce.tLevel+1 AS tLevel FROM @table1 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可以更加輕松愉快的用優雅簡潔的方式實現復雜的查詢。
讀到這里,這篇“SQL Server怎么使用T-SQL公用表表達式”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。