T-SQL 公用表表达式(CTE)
公用表表达式(CTE)
在编写T-SQL代码时,往往需要临时存储某些结果集。前面我们已经广泛使用和介绍了两种临时存储结果集的方法:临时表和表变量。除此之外,还可以使用公用表表达式的方法。公用表表达式(Common Table Expression)是SQL Server2005版本的引入的一个特性。CTE可以看组是一个临时的结果集,可以再接下来来的一个SELECT,INSERT,UPDATE,DELETE,MERGE语句中多次引用。使用公用表达式CTE可以让语句更加清晰简练。与公用表达式作用类似的还有临时表和表变量。下面给出三种方法的对比。
1、3种方法比较
(一)、临时表:需要在临时数据库TempDB中通过I/O操作来创建表结构,一旦用户推出SQL Server环境则自动被删除。
(二)、表变量:在内存中以表结构的形式存在,其定义与变量一致,其使用与表类似,不需要产生I/O。
(三)、公用表表达式:Common Table Expression,定义在内存中保存的临时存储结果集对象,不产生I/O,不需要按照表变量这样定义,使用方法和表类似。可以自己引用,也可以再查询中被多次引用。
2、WITH AS的含义
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
3、CTE的定义
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可以使其更加简洁
- GROUP BY语句可以直接作用于子查询所得的标量列
- 可以在一个语句中多次引用公用表表达式(CTE)
按照是否递归,可以将公用表(CTE)表达式分为递归公用表表达式和非递归公用表表达式.
非递归公用表表达式(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

结果如下:

递归公用表表达式(CTE):
对于递归公用表达式来说,只需要在语句中定义两部分:
- 基本语句
- 递归语句
先建一张表栏目表如下,栏目Id,栏目名称,栏目的父栏目。

现在使用CTE查询其每个栏目是第几层栏目的代码如下:

WITH COL_CTE(Id,Name,ParentId,tLevel )
AS
(
--基本语句
SELECT Id,Name,ParentId,0 AS tLevel FROM Col
WHERE ParentId = 0
UNION ALL
--递归语句
SELECT c.Id,c.Name,c.ParentId,ce.tLevel+1 AS tLevel FROM COL 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 Col
WHERE ParentId = 0
UNION ALL
--递归语句
SELECT c.Id,c.Name,c.ParentId,ce.tLevel+1 AS tLevel FROM COL 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可以更加轻松愉快的用优雅简洁的方式实现复杂的查询。
T-SQL 公用表表达式(CTE)的更多相关文章
- SQL Server进阶(六)表表达式--派生表、公用表表达式(CTE)、视图和内联表值函数
概述 表表达式是一种命名的查询表达式,代表一个有效地关系表.可以像其他表一样,在数据处理中使用表表达式. SQL Server支持四种类型的表表达式:派生表,公用表表达式,视图和内联表值函数. 为什么 ...
- SQL Server 公用表表达式(CTE)实现递归
公用表表达式简介: 公用表表达式 (CTE) 可以认为是在单个 SELECT.INSERT.UPDATE.DELETE 或 CREATE VIEW 语句的执行范围内定义的临时结果集.CTE 与派生表类 ...
- SQL Server 公用表表达式(CTE)实现递归的方法
公用表表达式简介: 公用表表达式 (CTE) 可以认为是在单个 SELECT.INSERT.UPDATE.DELETE 或 CREATE VIEW 语句的执行范围内定义的临时结果集.CTE 与派生表类 ...
- SQL 公用表表达式(CTE)
1.概念 公用表表达式(Common Table Expression)是SQL SERVER 2005版本之后引入的一个特性.CTE可以看作是一个临时的结果集,可以在接下来的一个SELECT,INS ...
- SQL Server温故系列(3):SQL 子查询 & 公用表表达式 CTE
1.子查询 Subqueries 1.1.单行子查询 1.2.多行子查询 1.3.相关子查询 1.4.嵌套子查询 1.5.子查询小结及性能问题 2.公用表表达式 CTE 2.1.普通公用表表达式 2. ...
- SQL Server 表表达式--派生表、公用表表达式(CTE)、视图和内联表值函数
概述 表表达式是一种命名的查询表达式,代表一个有效地关系表.可以像其他表一样,在数据处理中使用表表达式. SQL Server支持四种类型的表表达式:派生表,公用表表达式,视图和内联表值函数. 为什么 ...
- SQL Server中公用表表达式 CTE 递归的生成帮助数据,以及递归的典型应用
本文出处:http://www.cnblogs.com/wy123/p/5960825.html 我们在做开发的时候,有时候会需要一些帮助数据,必须需要连续的数字,连续间隔的时间点,连续的季度日期等等 ...
- sql server使用公用表表达式CTE通过递归方式编写通用函数自动生成连续数字和日期
问题:在数据库脚本开发中,有时需要生成一堆连续数字或者日期,例如yearly report就需要连续数字做年份,例如daily report就需要生成一定时间范围内的每一天日期.而自带的系统表mast ...
- 详解公用表表达式(CTE)
简介 对于SELECT查询语句来说,通常情况下,为了使T-SQL代码更加简洁和可读,在一个查询中引用另外的结果集都是通过视图而不是子查询来进行分解的.但是,视图是作为系统对象存在数据库中,那对于结果集 ...
随机推荐
- Entity Framework 4、5 多字段排序
public interface IOrderByExpression<TEntity> where TEntity : class { IOrderedQueryable<TEnt ...
- 设计模式之美:Prototype(原型)
索引 别名 意图 结构 参与者 适用性 缺点 效果 相关模式 命名约定 实现 实现方式(一):使用一个原型管理器. 实现方式(二):使用浅拷贝实现克隆(Clone)操作. 实现方式(三):使用深拷贝实 ...
- MMM互助金融/理财源码
1.1.1MMM互助金融配比系统源码销售 (3mphp.com/mmm-office.com) 联系QQ: 3375551869,全套源码,包含: 1 源码:安装.开发文档 2 数据库:含演示数据,自 ...
- error at ::0 can't find referenced pointcut解决办法(转载)
原文:http://blog.sina.com.cn/s/blog_9ecb0d9d0101fheg.html Spring中采用annotation的方式实现AOP代理,运行测试代码时抛出以下异常: ...
- windows装了双系统设置默认启动系统
我们装了双系统后,在开机设置时会自动启动其中一个系统,有时提示时间会很短,以至于不能判断自己是否装了双系统,以下,当电脑打开后,我们可以观察是否装了双系统 1.按组合键<Win+R>,打开 ...
- 如何引用jQuery实现下拉列表,点击展开,点击关闭。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- paip.java 以及JavaScript (js) 的关系以及区别
paip.java 以及JavaScript (js) 的关系以及区别 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http:// ...
- iOS-SVN、Git
版本控制SVN和Git使用详解 公司的实际开发中,在天朝使用较多的还是SVN,因为SVN是集中式的,在天朝上班你们都懂的! -----------------svn--------- ...
- Undefined symbols for architecture i386: "_deflate", referenced from:
Undefined symbols for architecture i386: "_deflate", referenced from: PlatCompress(enumCom ...
- LeetCode:Combination Sum I II
Combination Sum Given a set of candidate numbers (C) and a target number (T), find all unique combin ...