自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

SQL Server 2005/2008中的CTE應(yīng)用之遞歸查詢

數(shù)據(jù)庫(kù) SQL Server
本文我們主要介紹了SQL Server 2005/2008中的CTE應(yīng)用之遞歸查詢的相關(guān)知識(shí),并通過實(shí)際的例子進(jìn)行了說明,希望能夠?qū)δ兴斋@!

SQL Server 2005/2008中的CTE應(yīng)用之遞歸查詢是本文我們主要要介紹的內(nèi)容,接下來我們首先介紹一下MSDN中關(guān)于CTE的相關(guān)知識(shí),然后通過實(shí)際的例子進(jìn)行說明,希望能夠?qū)δ兴鶐椭?/p>

按照MSDN介紹

1、公用表表達(dá)式 (CTE) 可以認(rèn)為是在單個(gè) SELECT、INSERT、UPDATE、DELETE 或 CREATE VIEW 語(yǔ)句的執(zhí)行范圍內(nèi)定義的臨時(shí)結(jié)果集。CTE 與派生表類似,具體表現(xiàn)在不存儲(chǔ)為對(duì)象,并且只在查詢期間有效。與派生表的不同之處在于,CTE 可自引用,還可在同一查詢中引用多次。

CTE 可用于:

  • 創(chuàng)建遞歸查詢。有關(guān)詳細(xì)信息,請(qǐng)參閱使用公用表表達(dá)式的遞歸查詢。
  • 在不需要常規(guī)使用視圖時(shí)替換視圖,也就是說,不必將定義存儲(chǔ)在元數(shù)據(jù)中。
  • 啟用按從標(biāo)量嵌套 select 語(yǔ)句派生的列進(jìn)行分組,或者按不確定性函數(shù)或有外部訪問的函數(shù)進(jìn)行分組。
  • 在同一語(yǔ)句中多次引用生成的表。

使用CTE 可以獲得提高可讀性和輕松維護(hù)復(fù)雜查詢的優(yōu)點(diǎn)。查詢可以分為單獨(dú)塊、簡(jiǎn)單塊、邏輯生成塊。之后,這些簡(jiǎn)單塊可用于生成更復(fù)雜的臨時(shí) CTE,直到生成最終結(jié)果集??梢栽谟脩舳x的例程(如函數(shù)、存儲(chǔ)過程、觸發(fā)器或視圖)中定義 CTE。

2、公用表表達(dá)式 (CTE) 具有一個(gè)重要的優(yōu)點(diǎn),那就是能夠引用其自身,從而創(chuàng)建遞歸 CTE。遞歸 CTE 是一個(gè)重復(fù)執(zhí)行初始 CTE 以返回?cái)?shù)據(jù)子集直到獲取完整結(jié)果集的公用表表達(dá)式。當(dāng)某個(gè)查詢引用遞歸 CTE 時(shí),它即被稱為遞歸查詢。遞歸查詢通常用于返回分層數(shù)據(jù),例如:顯示某個(gè)組織圖中的雇員或物料清單方案(其中父級(jí)產(chǎn)品有一個(gè)或多個(gè)組件,而那些組件可能還有子組件,或者是其他父級(jí)產(chǎn)品的組件)中的數(shù)據(jù)。

遞歸CTE可以極大地簡(jiǎn)化在 SELECT、INSERT、UPDATE、DELETE 或 CREATE VIEW 語(yǔ)句中運(yùn)行遞歸查詢所需的代碼。在 SQL Server 的早期版本中,遞歸查詢通常需要使用臨時(shí)表、游標(biāo)和邏輯來控制遞歸步驟流。有關(guān)公用表表達(dá)式的詳細(xì)信息,請(qǐng)參閱使用公用表表達(dá)式。

為了描述方便,邀月特地列舉了一個(gè)常見的自關(guān)聯(lián)Table。

表結(jié)構(gòu)如下:

表結(jié)構(gòu):

  1. CREATE TABLE [dbo].[CategorySelf](  
  2.     [PKID] [int] IDENTITY(1,1) NOT NULL,  
  3.     [C_Name] [nvarchar](50) NOT NULL,  
  4.     [C_Level] [int] NOT NULL,  
  5.     [C_Code] [nvarchar](255) NULL,  
  6.     [C_Parent] [int] NOT NULL,  
  7.     [InsertTime] [datetime] NOT NULL,  
  8.     [InsertUser] [nvarchar](50) NULL,  
  9.     [UpdateTime] [datetime] NOT NULL,  
  10.     [UpdateUser] [nvarchar](50) NULL,  
  11.     [SortLevel] [int] NOT NULL,  
  12.     [CurrState] [smallint] NOT NULL,  
  13.     [F1] [int] NOT NULL,  
  14.     [F2] [nvarchar](255) NULL  
  15.  
  16.  CONSTRAINT [PK_OBJECTCATEGORYSELF] PRIMARY KEY CLUSTERED   
  17. (  
  18.     [PKID] ASC  
  19. )WITH (PAD_INDEX  = OFFSTATISTICS_NORECOMPUTE  = OFFIGNORE_DUP_KEY = OFFALLOW_ROW_LOCKS  = ONALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]  
  20. ) ON [PRIMARY]  
  21.  
  22. GO 

 

再插入一些測(cè)試數(shù)據(jù):

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

 

一個(gè)典型的應(yīng)用場(chǎng)景是:在這個(gè)自關(guān)聯(lián)的表中,查詢以PKID為2的分類包含所有子分類。也許很多情況下,我們不得不用臨時(shí)表\表變量\游標(biāo)等?,F(xiàn)在我們有了CTE,就簡(jiǎn)單多了。

  1. CTEDemo1  
  2. WITH SimpleRecursive(C_Name, PKID, C_Code,C_Parent)   
  3.     AS  
  4. (SELECT C_Name, PKID, C_Code,C_Parent  FROM CategorySelf WHERE PKID = 2 
  5. UNION ALL  
  6. SELECT p.C_Name, p.PKID, p.C_Code,p.C_parent  
  7.  FROM CategorySelf  P  INNER JOIN  
  8.  SimpleRecursive A ON A.PKID = P.C_Parent  
  9. )  
  10. SELECT sr.C_Name as C_Name, c.C_Name as C_ParentName,sr.C_Code as C_ParentCode  
  11. FROM SimpleRecursive sr inner join CategorySelf c  
  12. on sr.C_Parent=c.PKID 

 

查詢結(jié)果如下:

 

  1. C_Name    C_ParentName    C_ParentCode  
  2. 分類5    分類2    2  
  3. 分類8    分類5    2/5  
  4. 分類12    分類8    2/5/8  
  5. 分類13    分類8    2/5/8 

 

感覺怎么樣?如果我只想查詢第二層,而不是默認(rèn)的無限查詢下去,可以在上面的SQL后加一個(gè)選項(xiàng) Option(MAXRECURSION 5),注意5表示到第5層就不往下找了。如果只想找第二層,但實(shí)際結(jié)果有三層,此時(shí)會(huì)出錯(cuò):Msg 530, Level 16, State 1, Line 1.The statement terminated. The maximum recursion 1 has been exhausted before statement completion.

此時(shí)可以通過where條件來解決,而保證不出錯(cuò),看如下SQL語(yǔ)句:

  1. CTEDemo2  
  2. WITH SimpleRecursive(C_Name, PKID, C_Code,C_Parent,Sublevel)   
  3.     AS  
  4. (SELECT C_Name, PKID, C_Code,C_Parent,0  FROM CategorySelf WHERE PKID = 2 
  5. UNION ALL  
  6. SELECT p.C_Name, p.PKID, p.C_Code,p.C_parent,Sublevel+1  
  7.  FROM CategorySelf  P  INNER JOIN  
  8.  SimpleRecursive A ON A.PKID = P.C_Parent  
  9. )  
  10. SELECT sr.C_Name as C_Name, c.C_Name as C_ParentName,sr.C_Code as C_ParentCode  
  11. FROM SimpleRecursive sr inner join CategorySelf c  
  12. on sr.C_Parent=c.PKID  
  13. where SubLevel<=2 

 

查詢結(jié)果:

  1. C_Name    C_ParentName    C_ParentCode  
  2. 分類5    分類2    2  
  3. 分類8    分類5    2/5  

 

當(dāng)然,我們不是說CTE就是***的。通過好的表設(shè)計(jì)也可以某種程度上解決特定的問題。下面用常規(guī)的SQL實(shí)現(xiàn)上面這個(gè)需求。注意:上面表中有一個(gè)字段很重要,就是C_Code,編碼 ,格式如"1/2",“2/5/8"表示該分類的上級(jí)分類是1/2,2/5/8,這樣,我們查詢就簡(jiǎn)單多,查詢以PKID為2的分類包含所有子分類:

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

 

查詢以PKID為2的分類包含所有子分類,且級(jí)別不大于3

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

 

查詢結(jié)果同上,略去。這里我們看出,有時(shí)候,好的表結(jié)構(gòu)設(shè)計(jì)相當(dāng)重要。

關(guān)于SQL Server 2005/2008中的CTE應(yīng)用之遞歸查詢的相關(guān)知識(shí)就介紹到這里了,希望本次的介紹能夠?qū)δ兴斋@!

【編輯推薦】

  1. SQL Server多表查詢優(yōu)化方案總結(jié)
  2. SQL Server數(shù)據(jù)庫(kù)ISNULL函數(shù)的應(yīng)用實(shí)例
  3. SQL Server數(shù)據(jù)庫(kù)DATEPART的語(yǔ)法及使用實(shí)例
  4. SQL Server根據(jù)子節(jié)點(diǎn)查詢所有父節(jié)點(diǎn)的代碼示例
  5. SQL Server臟讀方式數(shù)據(jù)提取之NOLOCK和READPAST

 

責(zé)任編輯:趙鵬 來源: 博客園
相關(guān)推薦

2010-10-11 09:05:40

SQL Server

2011-02-28 13:19:50

SQL Server SQL死鎖

2011-03-11 10:35:31

SQL鎖定SQL Server

2011-03-11 13:26:32

SQL ServerBlocking阻塞

2011-08-19 14:03:36

SQL Server 檢索集合

2011-08-19 13:46:22

SQL Server 組裝有序集合

2011-09-01 13:24:42

SQL Server 呈現(xiàn)GeoRSS訂閱的Bing Maps

2011-08-01 09:09:07

SQL Server SQL Server 數(shù)據(jù)庫(kù)

2009-05-18 18:20:14

虛擬化Hyper-VWindows ser

2023-08-29 09:46:12

SQLCTE遞歸

2009-04-16 17:44:31

2009-04-16 18:15:19

動(dòng)作審核審核活動(dòng)SQL Server

2011-09-07 15:11:31

SQL Server同步

2010-10-21 15:13:20

SQL Server系

2011-02-18 17:31:18

SQL Server

2009-03-17 13:25:13

查詢遷移SQL Server

2010-07-13 16:48:14

SQL Server

2011-04-02 16:20:21

SQL SERVER 同步復(fù)制

2011-09-01 16:13:37

Visual StudSQL Server 存儲(chǔ)過程

2010-07-12 17:37:03

SQL Server
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)