亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 綜合 > 正文

SQL2005/2008中的CTE應用--遞歸查詢

2024-07-21 02:44:47
字體:
來源:轉載
供稿:網友

微軟從SQl2005起引入了CTE(Common Table ExPRession)以強化T-SQL。這是一個類似于非持久視圖的好東東。

按照MSDN介紹

1、公用表表達式 (CTE) 可以認為是在單個 SELECT、INSERT、UPDATE、DELETE 或 CREATE VIEW 語句的執行范圍內定義的臨時結果集 。CTE 與派生表類似,具體表現在不存儲為對象,并且只在查詢期間有效 。與派生表的不同之處在于,CTE 可自引用,還可在同一查詢中引用多次 。

CTE 可用于:

創建遞歸查詢。有關詳細信息,請參閱使用公用表表達式的遞歸查詢 。
在不需要常規使用視圖時替換視圖,也就是說,不必將定義存儲在元數據中。
啟用按從標量嵌套 select 語句派生的列進行分組,或者按不確定性函數或有外部訪問的函數進行分組。
在同一語句中多次引用生成的表。
使用 CTE 可以獲得提高可讀性和輕松維護復雜查詢的優點。查詢可以分為單獨塊、簡單塊、邏輯生成塊。之后,這些簡單塊可用于生成更復雜的臨時 CTE,直到生成最終結果集??梢栽谟脩舳x的例程(如函數、存儲過程、觸發器或視圖)中定義 CTE。

2、公用表表達式 (CTE) 具有一個重要的優點,那就是能夠引用其自身,從而創建遞歸 CTE 。遞歸 CTE 是一個重復執行初始 CTE 以返回數據子集直到獲取完整結果集的公用表表達式。當某個查詢引用遞歸 CTE 時,它即被稱為遞歸查詢 。遞歸查詢通常用于返回分層數據,例如:顯示某個組織圖中的雇員或物料清單方案(其中父級產品有一個或多個組件,而那些組件可能還有子組件,或者是其他父級產品的組件)中的數據。

遞歸 CTE 可以極大地簡化在 SELECT、INSERT、UPDATE、DELETE 或 CREATE VIEW 語句中運行遞歸查詢所需的代碼。在 SQL Server 的早期版本中,遞歸查詢通常需要使用臨時表、游標和邏輯來控制遞歸步驟流。有關公用表表達式的詳細信息,請參閱使用公用表表達式 。

 這里舉例說明如下:

 為了描述方便,邀月特地列舉了一個常見的自關聯Table

表結構如下:
CREATE TABLE [dbo].[CategorySelf](
    [PKID] [int] IDENTITY(1,1) NOT NULL,
    [C_Name] [nvarchar](50) NOT NULL,
    [C_Level] [int] NOT NULL,
    [C_Code] [nvarchar](255) NULL,
    [C_Parent] [int] NOT NULL,
    [InsertTime] [datetime] NOT NULL,
    [InsertUser] [nvarchar](50) NULL,
    [UpdateTime] [datetime] NOT NULL,
    [UpdateUser] [nvarchar](50) NULL,
    [SortLevel] [int] NOT NULL,
    [CurrState] [smallint] NOT NULL,
    [F1] [int] NOT NULL,
    [F2] [nvarchar](255) NULL
 CONSTRAINT [PK_OBJECTCATEGORYSELF] PRIMARY KEY CLUSTERED
(
    [PKID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

再插入一些測試數據

INSERT INTO [CategorySelf]([C_Name],[C_Level] ,[C_Code],[C_Parent] ,[InsertTime] ,[InsertUser] ,[UpdateTime]  ,[UpdateUser]  ,[SortLevel]  ,[CurrState]  ,[F1]  ,[F2])
select '分類1',1,'0',0,GETDATE(),'testUser',DATEADD(dd,1,getdate()),'CrackUser',13,0,1,'邀月備注' union all
select '分類2',1,'0',0,GETDATE(),'testUser',DATEADD(dd,78,getdate()),'CrackUser',12,0,1,'邀月備注' union all
select '分類3',1,'0',0,GETDATE(),'testUser',DATEADD(dd,6,getdate()),'CrackUser',10,0,1,'邀月備注' union all
select '分類4',2,'1',1,GETDATE(),'testUser',DATEADD(dd,75,getdate()),'CrackUser',19,0,1,'邀月備注' union all
select '分類5',2,'2',2,GETDATE(),'testUser',DATEADD(dd,3,getdate()),'CrackUser',17,0,1,'邀月備注' union all
select '分類6',3,'1/4',4,GETDATE(),'testUser',DATEADD(dd,4,getdate()),'CrackUser',16,0,1,'邀月備注' union all
select '分類7',3,'2/4',4,GETDATE(),'testUser',DATEADD(dd,5,getdate()),'CrackUser',4,0,1,'邀月備注' union all
select '分類8',3,'2/5',5,GETDATE(),'testUser',DATEADD(dd,6,getdate()),'CrackUser',3,0,1,'邀月備注' union all
select '分類9',4,'1/4/6',6,GETDATE(),'testUser',DATEADD(dd,7,getdate()),'CrackUser',5,0,1,'邀月備注' union all
select '分類10',4,'1/4/6',6,GETDATE(),'testUser',DATEADD(dd,7,getdate()),'CrackUser',63,0,1,'邀月備注' union all
select '分類11',4,'1/4/6',6,GETDATE(),'testUser',DATEADD(dd,8,getdate()),'CrackUser',83,0,1,'邀月備注' union all
select '分類12',4,'2/5/8',8,GETDATE(),'testUser',DATEADD(dd,10,getdate()),'CrackUser',3,0,1,'邀月備注' union all
select '分類13',4,'2/5/8',8,GETDATE(),'testUser',DATEADD(dd,15,getdate()),'CrackUser',1,0,1,'邀月備注'
 

一個典型的應用場景是:在這個自關聯的表中,查詢以PKID為2的分類包含所有子分類。也許很多情況下,我們不得不用臨時表或表變量等?,F在我們有了CTE,就簡單多了

WITH SimpleRecursive(C_Name, PKID, C_Code,C_Parent)
    AS
(SELECT C_Name, PKID, C_Code,C_Parent  FROM CategorySelf WHERE PKID = 2
UNION ALL
SELECT p.C_Name, p.PKID, p.C_Code,p.C_parent
 FROM CategorySelf  P  INNER JOIN
 SimpleRecursive A ON A.PKID = P.C_Parent
)
SELECT sr.C_Name as C_Name, c.C_Name as C_ParentName,sr.C_Code as C_ParentCode
FROM SimpleRecursive sr inner join CategorySelf c
on sr.C_Parent=c.PKID
查詢結果如下:C_Name    C_ParentName    C_ParentCode
分類5    分類2    2
分類8    分類5    2/5
分類12    分類8    2/5/8


分類13    分類8    2/5/8

 感覺怎么樣?如果我只想查詢第二層,而不是默認的無限查詢下去,

可以在上面的SQL后加一個選項 Option(MAXRECURSION 5) ,注意5表示到第5層就不往下找了。如果只想找第二層,但實際結果有三層,此時會出錯,

 Msg 530, Level 16, State 1, Line 1
The statement terminated. The maximum recursion 1 has been exhausted before statement completion.


此時可以通過where條件來解決,而保證不出錯,看如下SQL語句:

WITH SimpleRecursive(C_Name, PKID, C_Code,C_Parent,Sublevel)
    AS
(SELECT C_Name, PKID, C_Code,C_Parent,0  FROM CategorySelf WHERE PKID = 2
UNION ALL
SELECT p.C_Name, p.PKID, p.C_Code,p.C_parent,Sublevel+1
 FROM CategorySelf  P  INNER JOIN
 SimpleRecursive A ON A.PKID = P.C_Parent
)
SELECT sr.C_Name as C_Name, c.C_Name as C_ParentName,sr.C_Code as C_ParentCode
FROM SimpleRecursive sr inner join CategorySelf c
on sr.C_Parent=c.PKID
where SubLevel<=2
查詢結果:

C_Name    C_ParentName    C_ParentCode
分類5    分類2    2
分類8    分類5    2/5
當然,我們不是說CTE就是萬能的。通過好的表設計也可以某種程度上解決特定的問題。下面用常規的SQL實現上面這個需求。

注意:上面表中有一個字段很重要,就是C_Code,編碼 ,格式如"1/2",“2/5/8"表示該分類的上級分類是1/2,2/5/8

這樣,我們查詢就簡單多,查詢以PKID為2的分類包含所有子分類:

SELECT C_Name as C_Name, (Select top 1 C_Name from CategorySelf s where c.C_Parent=s.PKID) as C_ParentName,C_Code as C_ParentCode
from CategorySelf c where C_Code like '2/%'
查詢以PKID為2的分類包含所有子分類,且級別不大于3

SELECT C_Name as C_Name, (Select top 1 C_Name from CategorySelf s where c.C_Parent=s.PKID)  as C_ParentName,C_Code as C_ParentCode
from CategorySelf c where C_Code like '2/%' and C_Level<=3 

 查詢結果同上,略去。這里我們看出,有時候,好的表結構設計相當重要。

邀月于2009.10.23 1:40 完成分享。

有人很關心性能問題。目前沒有測試過。稍后會附上百萬級測試報告。不過,有兩點理解邀月忘了補充:

一、CTE其實是面向對象的,運行的基礎是CLR。一個很好的說明是With查詢語句中是區分字段的大小寫的 。即"C_Code"和"c_Code"是不一樣的,后者會報錯。這與普通的SQL語句不同 。

二、 這個應用示例重在簡化業務邏輯 ,即便是性能不佳,但對臨時表/表變量/游標等傳統處理方式是一種業務層次上的簡化或者說是優化。

助人等于自助!   3w@live.cn


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲欧美日韩在线高清直播| 国产在线视频91| 久久香蕉国产线看观看av| 国产精品99久久久久久人| 78m国产成人精品视频| 精品国产老师黑色丝袜高跟鞋| 久久夜色精品亚洲噜噜国产mv| 日韩亚洲一区二区| 国语对白做受69| 国产激情综合五月久久| 日韩精品视频在线播放| 国产成人综合亚洲| 最近2019中文免费高清视频观看www99| 日本不卡高字幕在线2019| 91极品视频在线| 日本欧美中文字幕| 91美女福利视频高清| 久久精品国产一区| 欧美精品成人在线| 社区色欧美激情 | 久久久国产成人精品| 久久久亚洲国产| 最近2019中文字幕一页二页| 国产精品盗摄久久久| 欧美亚洲第一区| 日韩在线观看av| 精品久久久久久| 亚洲aⅴ日韩av电影在线观看| 国产精品久久久久久久久久三级| 久久久精品久久| 日韩在线观看免费av| 欧美大片在线影院| 欧美日韩成人在线视频| 亚洲欧美自拍一区| 国产精品美女www爽爽爽视频| 国产精品欧美日韩| 日产日韩在线亚洲欧美| 精品久久久久久国产91| 亚洲电影免费观看高清完整版在线| 亚洲一区二区三区在线免费观看| 久久久亚洲国产天美传媒修理工| 欧美视频在线视频| 日韩电影免费在线观看| 色婷婷成人综合| 久久精品电影一区二区| 亚洲成成品网站| 国产精品视频久久久久| 91欧美精品午夜性色福利在线| 国产国语videosex另类| 日韩美女免费视频| 精品偷拍一区二区三区在线看| 日韩av电影在线网| 中文字幕少妇一区二区三区| 日韩av在线播放资源| 亚洲国产成人在线播放| 成人欧美一区二区三区黑人孕妇| 精品人伦一区二区三区蜜桃网站| 精品偷拍各种wc美女嘘嘘| 国产精品r级在线| 国产精品入口福利| 国产精品久久久久久亚洲调教| 影音先锋欧美精品| 亚洲国产日韩欧美在线动漫| 亚洲精品美女在线观看播放| 97久久久免费福利网址| 欧美激情亚洲视频| 国内成人精品一区| 久久成人18免费网站| 久久久久久久久久久免费精品| 午夜精品久久久久久99热软件| 日韩亚洲精品电影| 亚洲网在线观看| 精品女同一区二区三区在线播放| 高清一区二区三区四区五区| 欧美贵妇videos办公室| 精品久久久久久中文字幕一区奶水| 亚洲精品视频免费在线观看| 精品久久久久久中文字幕一区奶水| 中文字幕视频一区二区在线有码| 国产精品高精视频免费| 亚洲国产精品va在线看黑人| 日韩不卡中文字幕| 欧美午夜精品伦理| 欧美成年人视频网站| 中文字幕日韩精品有码视频| 国产成+人+综合+亚洲欧洲| 亲爱的老师9免费观看全集电视剧| 国产成人免费av电影| 日韩毛片在线看| 日韩在线观看免费网站| 丝袜美腿亚洲一区二区| 日韩欧美在线免费| 中文字幕日韩高清| 色老头一区二区三区| 成人亚洲欧美一区二区三区| 日韩美女在线观看一区| 国产亚洲一区精品| 日韩国产欧美精品在线| 日韩av在线网页| 国产欧美精品一区二区三区介绍| 亚洲美女av黄| 久久精品精品电影网| 亚洲福利在线视频| 日韩电视剧免费观看网站| yw.139尤物在线精品视频| 欧美精品精品精品精品免费| 97视频在线观看视频免费视频| 欧美大胆在线视频| 91精品久久久久久| 色婷婷成人综合| 草民午夜欧美限制a级福利片| 国产精品久久一区| 国产成人在线一区| 国产精品影片在线观看| 一区二区三区国产在线观看| 亚洲91精品在线| 久久亚洲精品一区二区| 国产精品99一区| 欧美又大粗又爽又黄大片视频| 久久99久国产精品黄毛片入口| 亚洲无限av看| 亚洲免费高清视频| 久久99精品久久久久久琪琪| 91精品国产91久久久久久最新| 亚洲欧美自拍一区| 成人精品一区二区三区| 久久久久久尹人网香蕉| www.亚洲一二| 亚洲欧洲在线观看| 国产精品久久久久久亚洲调教| 亚洲老板91色精品久久| 亚洲欧美成人在线| 亚洲欧美日韩高清| 久久伊人精品天天| 亚洲女人天堂av| 日韩av中文字幕在线| 4438全国成人免费| 久久久久国产精品免费网站| 国产成人精品国内自产拍免费看| 2019国产精品自在线拍国产不卡| 国产亚洲精品综合一区91| 国产一区二区三区在线观看视频| 国产精品91久久久| 欧美大片va欧美在线播放| 亚洲专区在线视频| 亚洲第一区在线| 亚洲精品一区二区网址| 精品久久久久久久久久国产| 欧美激情在线视频二区| 亚洲国产精品久久久久秋霞不卡| 日韩精品视频免费专区在线播放| 中文字幕精品一区二区精品| 日韩在线不卡视频| 人人澡人人澡人人看欧美| 精品无人区太爽高潮在线播放| 亚洲新声在线观看| 欧美精品情趣视频| 97免费视频在线播放| 日韩成人在线电影网| 国产一区二区激情| 国产精品日日摸夜夜添夜夜av| 久久久久久久激情视频| 亚洲天堂日韩电影| 欧美一级在线亚洲天堂|