通用表表达式(CTEs)是 SQL Server 2005的一项新功能。它们类似于alias(如在Select T1.* FROM MyTable T1中),不过功能更为强大。本质上,CTE是一个临时结果集,它仅仅存在于它发生的语句中。您可以在Select、Insert、Delete、 Update或CTEATE VIEW语句中建立一个CTE。CTE类似于派生表,但拥有几项优点。
CTE的优点
与派生表不同,CTE能够引用自己本身。如果您不必存储视图,您可以用一个CTE来代替它。在一个语句中,您还可以多次引用CTE。应用CTE,您可以通过一个派生栏对结果进行分组。
之前,我曾写过有关原子和分子查询的文章。原子查询建立一个表,而分子查询建立在原子查询之上,提供清晰与重复利用。应用CTE也可以达到同样的目的。您可以将查询区域分割成可读的“块”,然后用这些块建立一个复杂的查询。执行递归查询是CTE最重要也是最强大的功能。
建立CTE
CTE通过关键字WITH建立,其模板为:
WITH CTE_name[ (column_name [,...n] ) ] |
如果在CTE定义中提到的栏名称是唯一的,那么您可以不必给它们命名。不过,您同样也可以对它们重新命名。
下面的例子应用到SQL Server 2005中的AdventureWorks样本数据库。这个数据库被高度规格化,因此需要几个连接来集合与雇员有关的信息。视图简化了这一操作,但也收集了所有有关雇员的信息,而您可能仅仅需要其中一部分资料。
AdventureWorks的雇员数据分布在几个表中;而且,雇员与经理被存储在同一个表中(HumanResources.Employee),而他们的姓名(及其它数据)则存储在Person.Contact表中,这使得这个问题更加复杂。
首先,我们建立一个恢复雇员姓名的CTE。
WITH cte_Employee |
然后,我们可从CTE中选择一栏或几栏,就像它是一个标准的表或视图。
接着我们再进一步。我们需要雇员和他们经理的姓名,于是我们使用CTE两次,把它自身连接起来。下面是完整的查询代码:
WITH cte_Employee |
限制:不能在一个语句中建立两个CTE。
CTE(二)我先简单介绍一下CTE(Common Table Expression)是什么 ,然后简要介绍下用法和注意事项
什么是CTE:Common Table Expression:是Sql2005推出的语法,类似内置临时表,创建后自动消亡,在cte中可以进行递归查询等操作
cte可以看作临时表,但是它的生命周期仅存在于访问每一次的TSQL批处理语法中,而一般临时对象的生命周期与连接同在
一、生命周期
注意CTE和临时表有个重要的区别,就是生存周期,那么CTE的生存周期到底有多久呢,我们看下面的语句
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
紧跟在with语句后面的第一条语句是有效果的,执行第二条前对象就消亡了,也就是说cte的存在周期是with语句的下一条语句,所以,cte不能替代 临时表,但是适用于那种只用一次的临时表的场合,在这种情况下,使用cte不会造成日志文件的增大,也不需要手工销毁临时表
二、使用冒号分割
使用cte还有一个地方需要注意,如果在存储过程或者语句中,cte不是一个这个批处理的第一条语句,那么前一条语句必须要以冒号“;”结尾,如下
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
这 时执行报错:Incorrect syntax near the keyword 'with'. If this statement is a common table expression or an xmlnamespaces clause, the previous statement must be terminated with a semicolon.
如果你在set @a=5后面加一个;那么就可以顺利执行了,
三、使用限制
with语句下一定要有语句,并且一定要是select,update,delete,insert语句,如果没有语句会报:Incorrect syntax near ')'.但是如果你的with语句下跟了一个比如set 语句,如下
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
总结
CTE是SQL Server 2005的一项强大而灵活的功能。它使得SQL Server的可读性更强,更易于管理,降低了查询的复杂程度。如上所述,您可以在一个SQL Server语句中多次应用CTE。