All articles| All Pictures| All Softwares| All Video| Go home page| Write articles| Upload pictures

Reading number is top 10 articles
asp.net2.0中读取web.config数据库连接字符串2种方法_.net资料_编程技术
delphi事件的定义及作用
如何在SQL Server中对行进行动态编号_[SQL Server教程]
PHP,存取,MySQL,数据库的一个例子_php资料_编程技术
xml的解析处理以及其他_[XML教程]
PHP实现在图片中添加中文文字_[PHP教程]
用.net,处理xmlHttp发送异步请求_.net资料_编程技术
Asp.net连接数据实例(ACCESS版)_[Asp.Net教程]
asp.net2.0服务器控件之RadioButton控件
小记存储过程中经常用到的本周,本月,本年函数_[SQL,Server教程]
Reading number is top 10 pictures
中国处女图鉴1
A man's favorite things6
谁认识这位校花
Ashlynn Brooke show proud chest measurement1
30 beautiful school beauty3
美丽的桂林风光1
The money of more than 100 countries and regions15
So beauty, will let you spray blood8
中国的十元人民币的秘密
住院一星期,检测费两万
Download software ranking
Professional killers2 for Android
在线棋牌游戏3.05版
Ashlynn Video1
DreamWeaver8
Twenty piece of palm leaf
C#COM编程指南
Boxer's Top ten classic battle6
尖东毒玫瑰A
Photoshop 8.0图象编辑软件
linux高级编程
delv published in(发表于) 2013/12/30 4:37:08 Edit(编辑)
SQL,Server中的CTE_mssql学习_编程技术

SQL,Server中的CTE_mssql学习_编程技术

SQL Server中的CTE_mssql学习_编程技术-你的首页-uuhomepage.com
1、公用表表达式 (CTE) 可以认为是在单个 SELECT、INSERT、UPDATE、DELETE 或 CREATE VIEW 语句的执行范围内定义的临时结果集。CTE 与派生表类似,具体表现在不存储为对象,并且只在查询期间有效。与派生表的不同之处在于,CTE 可自引用,还可在同一查询中引用多次。
  CTE 可用于:
  创建递归查询。有关详细信息,请参阅使用公用表表达式的递归查询。
  在不需要常规使用视图时替换视图,也就是说,不必将定义存储在元数据中。
  启用按从标量嵌套 select 语句派生的列进行分组,或者按不确定性函数或有外部访问的函数进行分组。
  在同一语句中多次引用生成的表。
  使用 CTE 可以获得提高可读性和轻松维护复杂查询的优点。查询可以分为单独块、简单块、逻辑生成块。之后,这些简单块可用于生成更复杂的临时 CTE,直到生成最终结果集。可以在用户定义的例程(如函数、存储过程、触发器或视图)中定义 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语句不同。
  二、 这个应用示例重在简化业务逻辑,即便是性能不佳,但对临时表\表变量\游标等传统处理方式是一种业务层次上的简化或者说是优化。




添加到del.icio.us 添加到新浪ViVi 添加到百度搜藏 添加到POCO网摘 添加到天天网摘365Key 添加到和讯网摘 添加到天极网摘 添加到黑米书签 添加到QQ书签 添加到雅虎收藏 添加到奇客发现 diigo it 添加到饭否 添加到飞豆订阅 添加到抓虾收藏 添加到鲜果订阅 digg it 貼到funP 添加到有道阅读 Live Favorites 添加到Newsvine 打印本页 用Email发送本页 在Facebook上分享


Disclaimer Privacy Policy About us Site Map

If you have any requirements, please contact webmaster。(如果有什么要求,请联系站长)
Copyright ©2011-
uuhomepage.com, Inc. All rights reserved.