1、概念
公用表表达式(Common Table Expression)是SQL SERVER 2005版本之后引入的一个特性.CTE可以看作是一个临时的结果集,可以在接下来的一个SELECT,INSERT,UPDATE,DELETE,MERGE语句中被多次引用。使用公用表达式可以让语句更加清晰简练.
除此之外,根据微软对CTE好处的描述,可以归结为四点:
- 可以定义递归公用表表达式(CTE)
- 当不需要将结果集作为视图被多个地方引用时,CTE可以使其更加简洁
- GROUP BY语句可以直接作用于子查询所得的标量列
- 可以在一个语句中多次引用公用表表达式(CTE)
2、数据
姓名 课程 分数 张三 语文 74 张三 数学 83 张三 物理 93 李四 语文 74 李四 数学 84 李四 物理 94
3、嵌套的查询语句
select * from tb where 分数 in (select 分数 from tb where 分数>90)
上面的查询语句使用了一个子查询。虽然这条SQL语句并不复杂,但如果嵌套的层次过多,会使SQL语句非常难以阅读和维护。
因此,也可以使用表变量的方式来解决这个问题,SQL语句如下:
declare @t table (分数 int) insert into @t (分数) (select 分数 from tb where 分数>90) select * from tb where 分数 in (select * from @t)
虽然上面的SQL语句要比第一种方式更复杂,但却将子查询放在了表变量@t中,这样做将使SQL语句更容易维护,但又会带来另一个问题,就是性能的损失。
由于表变量实际上使用了临时表,从而增加了额外的I/O开销,因此,表变量的方式并不太适合数据量大且频繁查询的情况。
为此,在SQL Server 中提供了另外一种解决方案,这就是公用表表达式(CTE),使用CTE,可以使SQL语句的可维护性,同时,CTE要比表变量的效率高得多。
with cr as ( select 分数 from tb where 分数>90 ) select * from tb where 分数 in (select * from cr)
4、在使用CTE时应注意如下几点:
4.1. CTE后面必须直接跟使用CTE的SQL语句(如select、insert、update等),否则,CTE将失效。如下面的SQL语句将无法正常使用CTE:
with cr as ( select 分数 from tb where 分数>90 ) select * from tb --应将这条SQL语句去掉 select * from tb where 分数 in (select * from cr) --使用CTE的SQL语句应紧跟在相关的CTE后面
4.2. CTE后面也可以跟其他的CTE,但只能使用一个with,多个CTE中间用逗号(,)分隔,如下面的SQL语句所示
with cr1 as ( select * from tb ), cr2 as ( select * from tb ), cr3 as ( select * from tb ) select a.* from cr1 a, cr2 b, cr3 c where a.分数 = b.分数 and a.分数 = c.分数
4.3. 如果CTE的表达式名称与某个数据表或视图重名,则紧跟在该CTE后面的SQL语句使用的仍然是CTE,当然,后面的SQL语句使用的就是数据表或视图了,如下面的SQL语句所示:
with tb as ( select Name from Student ) select * from tb
4.4. 如果将 CTE 用在属于批处理的一部分的语句中,那么在它之前的语句必须以分号结尾,如下面的SQL所示:
declare @t table (分数 int) insert into @t (分数) (select 分数 from tb where 分数>90);--必须加分号 with tr as ( select 分数 from tb where 分数 in (select * from @t) ) select * from tr