1、介绍
对于SELECT查询语句来说,通常情况下,为了使T-SQL代码更加简洁和可读,在一个查询中引用另外的结果集都是通过视图而不是子查询来进行分解的.但是,视图是作为系统对象存在数据库中,那对于结果集仅仅需要在存储过程或是用户自定义函数中使用一次的时候,使用视图就显得有些奢侈了.
公用表表达式(Common Table Expression)是SQL SERVER 2005版本之后引入的一个特性.CTE可以看作是一个临时的结果集,可以在接下来的一个SELECT,INSERT,UPDATE,DELETE,MERGE语句中被多次引用。使用公用表达式可以让语句更加清晰简练.
优势归结为四点:
[1]可以定义递归公用表表达式(CTE);
[2]当不需要将结果集作为视图被多个地方引用时,CTE可以使其更加简洁;
[3]GROUP BY语句可以直接作用于子查询所得的标量列;
[4]可以在一个语句中多次引用公用表表达式(CTE)。
2、定义
公用表达式包含三部分:
[1]公用表表达式的名字(在WITH之后)
[2]所涉及的列名(可选)
[3]一个SELECT语句(紧跟AS之后)
WITH expression_name [ ( column_name [,...n] ) ] AS ( CTE_query_definition )
3、公用表表达式类型
按照是否递归,可以将公用表(CTE)表达式分为递归公用表表达式和非递归公用表表达式.
[1]非递归公用表表达式
查询结果仅仅一次性返回一个结果集用于外部查询调用。并不在其定义的语句中调用其自身的CTE,其使用方式和视图以及子查询一致。
当然,公用表表达式的好处之一是可以在接下来一条语句中多次引用;由于CTE只能在接下来一条语句中使用,因此,当需要接下来的一条语句中引用多个CTE时,可以定义多个,中间用逗号分隔。
[2]递归公用表表达式
递归公用表表达式很像派生表(Derived Tables ),指的是在CTE内的语句中调用其自身的CTE。与派生表不同的是,CTE可以在一次定义多次进行派生递归.对于递归的概念,是指一个函数或是过程直接或者间接的调用其自身。
对于递归公用表达式来说,同样需要在语句中定义两部分:(1)基本语句;(2)递归语句。
在SQL这两部分通过UNION ALL连接结果集进行返回。可用此方法实现树查询。
CREATE TABLE Employee( EmployeeId INT IDENTITY(1,1) NOT NULL, ManageId INT, Name NVARCHAR(20) ); INSERT INTO Employee VALUES(0,'a'),(1,'b'),(2,'c'); WITH CTE_E (EmployeeId, ManageId, Name, Tlevel) AS( --基本语句 SELECT EmployeeId, ManageId, Name, 0 AS Tlevel FROM Employee WHERE ManageId = 0 UNION ALL --递归语句 SELECT a.EmployeeId, a.ManageId, a.Name, b.Tlevel+1 AS Tlevel FROM Employee a INNER JOIN CTE_E b ON a.ManageId = b.EmployeeId ) Select * From CTE_E;
当然,越强大的力量,就需要被约束.如果使用不当的话,递归CTE可能会出现无限递归。从而大量消耗SQL Server的服务器资源.因此,SQL Server提供了OPTION选项( OPTION(MAXRECURSION 2) ),可以设定最大的递归次数。