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

首頁 > 數據庫 > SQL Server > 正文

SQL Server中的CTE

2019-11-03 08:36:04
字體:
來源:轉載
供稿:網友
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,'1/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的分類包含所有子分類。也許很多情況下,我們不得不用臨時表/表變量/游標等。現在我們有了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


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

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

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

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

下一篇: SQL中CASE使用

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美精品免费播放| 国产精品v日韩精品| 久久久精品视频成人| 亚洲色图色老头| 日韩电影在线观看中文字幕| 欧美大全免费观看电视剧大泉洋| 性欧美xxxx| 亚洲第一福利网| 亚洲欧美一区二区精品久久久| 欧美激情亚洲精品| 久久视频这里只有精品| 精品国产鲁一鲁一区二区张丽| 久久久999精品| 久久精品国产亚洲7777| 久久精品视频在线播放| 午夜精品国产精品大乳美女| 亚洲开心激情网| 综合av色偷偷网| 91高清免费在线观看| 疯狂欧美牲乱大交777| 久久精品久久久久久国产 免费| 亚洲乱码av中文一区二区| 2021久久精品国产99国产精品| 国产视频综合在线| 91精品视频在线看| 国产偷亚洲偷欧美偷精品| 欧美在线视频网站| 91精品视频在线免费观看| 日产精品99久久久久久| 亚洲精品一区二区久| 欧美黑人xxxx| 97免费视频在线播放| 美女黄色丝袜一区| 国产精品扒开腿做爽爽爽视频| 久久精品国产综合| 国产精品一区二区三区久久久| 精品国产区一区二区三区在线观看| 久久久久www| 国产精品久久久久久久久免费看| 亚洲精品国产免费| 国产日韩综合一区二区性色av| 九九热r在线视频精品| 欧美xxxx14xxxxx性爽| 欧美另类99xxxxx| 欧美性受xxxx白人性爽| 成人免费福利在线| 国产精品免费小视频| 国产欧美中文字幕| 97久久国产精品| 精品视频在线导航| 亚洲女在线观看| 亚洲成人精品久久久| 中日韩美女免费视频网址在线观看| 日韩精品极品视频免费观看| 2020国产精品视频| 国产精品福利在线观看网址| 久久精品人人做人人爽| 日韩精品亚洲视频| 色偷偷噜噜噜亚洲男人| 国产精品久久一| 性视频1819p久久| 日韩中文娱乐网| 一区二区在线视频播放| 久久国产一区二区三区| 欧美激情欧美激情在线五月| 欧美老女人在线视频| 欧美午夜视频一区二区| 国产精品老牛影院在线观看| 国产精品户外野外| 久久久精品日本| 国产一区二区三区在线免费观看| 中文字幕一区日韩电影| 国产精品欧美日韩一区二区| 亚洲夜晚福利在线观看| 国产精品69精品一区二区三区| 久久久久亚洲精品| 在线亚洲午夜片av大片| 国产一区二区三区在线观看网站| 成人免费网站在线| 欧美一级淫片丝袜脚交| www.日本久久久久com.| 欧美精品在线网站| 久久综合免费视频| 午夜精品久久久久久99热软件| 高跟丝袜一区二区三区| 亚洲欧洲激情在线| 日韩毛片在线看| 国产精品久久久久久久久久久久久久| 日韩中文在线不卡| 日本精品中文字幕| 成人免费看片视频| 日韩在线www| 久久天天躁夜夜躁狠狠躁2022| 成人亚洲欧美一区二区三区| 欧美精品www| 亚洲一区二区三| 亚洲天堂免费观看| 日韩免费观看视频| 久久在精品线影院精品国产| 国产精品欧美亚洲777777| 日韩美女免费视频| 日韩大片在线观看视频| 欧美激情精品久久久久久大尺度| 国产精品高清在线观看| 成人乱人伦精品视频在线观看| 国产91色在线免费| 欧美福利视频网站| 国产精品第10页| 久久免费成人精品视频| 国产精品揄拍一区二区| 日韩欧美国产网站| 中文字幕久热精品在线视频| 欧美日韩激情视频| 欧美成人免费大片| 亚洲福利在线播放| 97在线视频国产| 欧美另类在线播放| 久久人人看视频| 国产精品美女久久久久av超清| 亚洲成人999| 久久免费精品日本久久中文字幕| 91精品国产自产91精品| 亚洲国产精品久久| 亚洲国产精品99| 国产精品国产亚洲伊人久久| 国产三级精品网站| 欧美噜噜久久久xxx| 亚洲xxxxx性| 国产精品999| 久久久999精品| 精品国产欧美成人夜夜嗨| 日韩极品精品视频免费观看| 一本色道久久综合亚洲精品小说| 亚洲伊人久久综合| 亚洲高清一二三区| 国产亚洲精品久久久久久牛牛| 亚洲成人精品视频在线观看| 亚洲最大成人免费视频| 久久夜色精品亚洲噜噜国产mv| 久久精品99久久久香蕉| 日韩视频中文字幕| 久久免费少妇高潮久久精品99| 亚洲社区在线观看| 91精品啪aⅴ在线观看国产| 久久精品亚洲国产| 亚洲黄色在线观看| 国产精品偷伦视频免费观看国产| 久久精品国产69国产精品亚洲| 国产精品亚洲第一区| 国产精品亚洲综合天堂夜夜| 日韩av在线天堂网| 国产精品永久免费| 最近2019年日本中文免费字幕| 国产成人精品最新| 国产亚洲精品久久久久久| www.午夜精品| 久久精品国产精品| 欧美三级xxx| 国产精品高潮呻吟视频| 欧美孕妇性xx| 亚洲国产精品女人久久久| 国产欧美一区二区三区久久| 欧美高清自拍一区| 在线播放日韩欧美|