T-SQL公用表表达式有何作用及好处,怎么用
Admin 2022-08-04 群英技术资讯 950 次浏览
这篇文章给大家分享的是“T-SQL公用表表达式有何作用及好处,怎么用”,对大家学习和理解有一定的参考价值和帮助,有这方面学习需要的朋友,接下来就跟随小编一起学习一下吧。在编写T-SQL代码时,往往需要临时存储某些结果集。前面我们已经广泛使用和介绍了两种临时存储结果集的方法:临时表和表变量。除此之外,还可以使用公用表表达式的方法。
公用表表达式(Common Table Expression)是SQL Server2005版本的引入的一个特性。CTE可以看组是一个临时的结果集,可以再接下来来的一个SELECT,INSERT,UPDATE,DELETE,MERGE语句中多次引用。
使用公用表达式CTE可以让语句更加清晰简练。与公用表达式作用类似的还有临时表和表变量。下面给出三种方法的对比。
根据微软对CTE好处的描述,可以归结为四点:
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
CTE的定义语法如下,主要包括3个部分。
WITH expression_name [(column_name [,...n] )] AS ( cte_query_definition )
按照是否递归,可以将公用表(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;
结果如下:

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

现在使用CTE查询其每个栏目是第几层栏目的代码如下:
declare @table1 table(id int, Name varchar(10), ParentId int);
insert into @table1(id, Name, ParentId)
values(1, '国内新闻', 0),
(2, '广东新闻', 1),
(3, '广州新闻', 2),
(4, '天河新闻', 3),
(5, '山东新闻', 1),
(5, '青岛新闻', 5);
select * from @table1;
with COL_CTE(Id, Name, ParentId, tLevel) as (
--基本语句
select id, Name, ParentId, 0 as tLevel from @table1 where ParentId=0
union all
--递归语句
select c.id, c.Name, c.ParentId, ce.tLevel+1 as tLevel from @table1 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 @table1 WHERE ParentId = 0
UNION ALL
--递归语句
SELECT c.Id,c.Name,c.ParentId,ce.tLevel+1 AS tLevel FROM @table1 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可以更加轻松愉快的用优雅简洁的方式实现复杂的查询。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
COUNT() 函数返回匹配指定条件的行数。SQL COUNT(column_name) 语法:COUNT(column_name) 函数返回指定列的值的数目(NULL 不计入)
这篇文章介绍了SQL Server中Sequence对象的用法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
这篇文章主要给大家介绍sql自定义函数的内容,很多朋友对于自定义函数的用处、自定义函数与存储过程区别不是很了解,因此下文给大家具体的介绍一下, 接下来跟随小编来了解一下吧。
这篇文章主要介绍了循环和游标在Sql存储过程中使用及sql如何使用cursor写一个简单的循环的相关资料,需要的朋友可以参考下
SQL UNION运算符用于组合两个或更多SELECT语句的结果集,而不返回任何重复的行。UNION中的每个SELECT语句必须具有相同的列数,这些列也必须具有相似的数据类型,每个SELECT语句中的列也必须以相同的顺序排列,每个SELECT语句必须有相同数目的列表达式 但是每个SELECT语句的长度不必相同
成为群英会员,开启智能安全云计算之旅
立即注册关注或联系群英网络
7x24小时售前:400-678-4567
7x24小时售后:0668-2555666
24小时QQ客服
群英微信公众号
CNNIC域名投诉举报处理平台
服务电话:010-58813000
服务邮箱:service@cnnic.cn
投诉与建议:0668-2555555
Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008