sql server中的cte
从SQL Server 2005开始,提供了CTE(Common Table Expression,公用表表达式)的语法支持。
CTE是定义在SELECT、INSERT、UPDATE或DELETE语句中的临时命名的结果集,同时CTE也可以用在视图的定义中。
在CTE中可以包括对自身的引用,因此这种表达式也被称为递归CTE。
CTE的优点
公用表表达式提供的功能其实和视图差不多,但是它不像视图一样把SQL语句保存在我们的数据库里面。
微软官方给出的使用CTE的优势:
1.可以编写一个递归查询。
2.要使用一个类似视图的功能,但是又不想把这个查询SQL语句的定义保存到数据库中。
3.要引用一个返回数据的SQL语句多次,只需要定义一次。
使用CTE可以把复杂的SQL语句按照逻辑分成简单独立的几个公用表表达式(CTE),这样的最大优势就是能够提高SQL语句的可读性和可维护性。
总结就是,CTE主要可以用于树结构的递归和简化SQL语句,增加可读性和可维护性。
CTE的使用场景
由于业务需要,我们经常会写一些比较复杂的SQL语句,里面可能会包含很多的JOIN或子查询,要维护和理清这种N多个表的JOIN关系是一件非常头疼的事情,而使用CTE就可以使维护和理解复杂的SQL语句变得简单一些。
在开发的时候使用子查询,一般是这种情况:需要从一个复杂的子查询,甚至多级子查询嵌套。在这种情况下,在整个SQL语句里面,无论你是直接写SQL语句还是把这段SQL语句包装成子查询然后用别名来访问,当业务需求越来越变得复杂,你可能随时需要修改这个长且复杂的SQL语句段,而维护这种复杂的、可读性差的SQL语句简直是噩梦。
有了CTE只有,我们就可以使用CTE来定义一个SQL语句,并且为这个SQL语句执行后返回的结果集定义一个别名,接下来就可以通过这个别名来引用这些预先执行返回的数据集,就像使用普通的表一样。
CTE的语法
一个公用表表达式主要包含三个主要部分:
1.CET名称(WITH后面,列名列之前)。
2.列名列(可选)。
3.CET查询语句主体(AS后面括起来的内容)。
with expression_name (column_name, …) as (
-- cte_query_definition cte查询语句定义
)
要注意的是,如果要定义多个表达式,需要用逗号分隔。
使用CTE进行多次查询
CTE是可以在跟随其后的查询中多次引用的。
with tmp(id) as (
select id from users where name like '杨%';
)
select * from tmp;
select * from orders where userId in (select id from tmp);
使用CTE递归查询树形记录(向上查询父节点或向下查询子节点)
CTE有一个特性就是它是支持递归的,即在CTE的查询语句主体中引用自身。这一特性常常被用在查询树形记录。
with subqry(id, pid, name) as (
select cb.id,
cb.pid,
cb.namefrom cb
where cb.id = ''
union all
select cb.id,
cb.pid,
cb.namefrom cb, subqry
where cb.id = subqry.pid
)
select distinct *
from subqry
with subqry(id, pid, name) as (
select cb.id,
cb.pid,
cb.name
from cb
where cb.id = ''
union all
select cb.id,
cb.pid,
cb.name
from cb, subqry
where cb.pid = subqry.id
)
select distinct *
from subqry
使用CTE的注意事项
1.CTE后面必须紧跟着使用CTE的SQL语句,比如SELECT、INSERT和UPDATE等,否则CTE将失效(直接报错)。
with tmp(id) as (
select id from users where favor = '牛奶';
)
select 1;
select * from tmp;
像上面的语句就会报【定义了公用表表达式,但没有使用】的错。
2.CTE后面也可以跟其他的CTE,但是只能使用一个WITH,多个CTE中间用逗号【,】隔开。
with
milk(id) as (
select id from users where favor = '牛奶';
),
apple(id) as (
select id from users where favor = '苹果';
)
select id from milk, apple where milk.id = apple.id
3.如果CTE表达式名称与某个实体表或者视图重名,则紧跟在该CTE后面的SQL语句使用的仍然是CTE。
要注意的是,后面再使用该同名就是使用实体表或视图了。
4.CTE可以引用自身,也可以引用在同一个WITH子句中预先定义的CTE,但是不允许前向引用(定义前使用)。
5.不能在CTE_QUERY_DEFINITION(CTE查询语句定义)中使用以下子句:
(1)COMPUTE或COMPUTE BY
(2)ORDER BY(除非指定了TOP 子句)
(3)INTO
(4)带有查询提示的OPTION 子句
(5)FOR XML
(6)FOR BROWSE
6.如果将CTE用于批处理的一部分的语句中,那么在它之前的语句必须以分号结尾。
declare @id int
set @id = 0; -- 这里必须以分号结尾
;with tmp(name) as ( -- 在with前加上分号避免出错
select name from users where unrequitedLove = '静静';
)
select * from tmp;
当然了,一个良好的习惯(技巧)是在写CTE的时候统统在WITH前加上分号【;】,这样就能避免出错,比如上面的语句。
总结
如果经常写查询的话,比如一些统计分析或制作报表,CTE是会经常使用到的,因为使用起来十分方便,也几乎不会有什么副作用,在一定程度上能够提高开发和维护的效率。另外,其递归属性在树形记录的查询中的应用十分广泛,是一个要好好掌握的语法。
"我还是很喜欢你,像樵人薄暮,倦鸟归栖。"
sql server中的cte的更多相关文章
- SQL Server中CTE的另一种递归方式-从底层向上递归
SQL Server中的公共表表达式(Common Table Expression,CTE)提供了一种便利的方式使得我们进行递归查询.所谓递归查询方便对某个表进行不断的递归从而更加容易的获得 ...
- Sql Server中不常用的表运算符之APPLY(2)
在Sql Server中不常用的表运算符之APPLY(1)中提到,SQL2005中新支持的APPLY的特性:1.可以直接将表表达式(表值函数或者子查询)作为APPLY语句的右表连接左表.2.由于使用A ...
- SQL Server 中 with tmp 临时表的用法
SQL Server 中 with tmp 临时表的用法 ----------with临时表用法,有时候采用临时表比采用in的效率更高,避免了全表扫描. 实例中实现了查询普通题.大题.子题目的sql ...
- 转载: SQL Server中的索引
http://www.blogjava.net/wangdetian168/archive/2011/03/07/347192.html 1 SQL Server中的索引 索引是与表或视图关联的磁盘上 ...
- c#Winform程序调用app.config文件配置数据库连接字符串 SQL Server文章目录 浅谈SQL Server中统计对于查询的影响 有关索引的DMV SQL Server中的执行引擎入门 【译】表变量和临时表的比较 对于表列数据类型选择的一点思考 SQL Server复制入门(一)----复制简介 操作系统中的进程与线程
c#Winform程序调用app.config文件配置数据库连接字符串 你新建winform项目的时候,会有一个app.config的配置文件,写在里面的<connectionStrings n ...
- sql server中的临时表、表变量和公用表表达式
在编写T-SQL语句的时候,SQL Server提供了三种方法临时存储某些结果集,分别是临时表.表变量和公用表表达式. 临时表 临时表需要在临时数据库TempDB中通过I/O操作来创建表结构,一旦用户 ...
- SQL Server中的高可用性(2)----文件与文件组
在谈到SQL Server的高可用性之前,我们首先要谈一谈单实例的高可用性.在单实例的高可用性中,不可忽略的就是文件和文件组的高可用性.SQL Server允许在某些文件损坏或离线的情况下,允 ...
- SQL Server中SELECT会真的阻塞SELECT吗?
在SQL Server中,我们知道一个SELECT语句执行过程中只会申请一些意向共享锁(IS) 与共享锁(S), 例如我使用SQL Profile跟踪会话86执行SELECT * FROM dbo.T ...
- Microsoft SQL Server中的事务与并发详解
本篇索引: 1.事务 2.锁定和阻塞 3.隔离级别 4.死锁 一.事务 1.1 事务的概念 事务是作为单个工作单元而执行的一系列操作,比如查询和修改数据等. 事务是数据库并发控制的基本单位,一条或者一 ...
随机推荐
- 默认文档接卸--手机web app开发笔记(二)
首先我们启动HBuilderX2.0 ,界面如图2-1所示 图2-1 软件开发界面 单击“文件—新建—项目”,弹出新建项目管理界面,我们在里面进行了项目类型选择“5+APP”.项目名称填写“编程之路” ...
- [ PyQt入门教程 ] PyQt5环境搭建和配置
PyQt入门系列教程主要目的是希望通过该系列课程学习,可以使用PyQt5工具快速实现简单的界面开发,包括界面设计.布局管理以及业务逻辑实现(信号与槽).简单说就是可以使用PyQt5工具快速画一个控件摆 ...
- javascript基础学习第三天
☞ 命名法: 小驼峰命名法 和 大驼峰命名法(帕斯卡命名法) 变量命名规则:遵循小驼峰命名法 [变量名第一个字母小写后面每一个单词的首字母大写] var userNameAge; 函数命名规则:遵循帕 ...
- 【JDK】JDK源码分析-ArrayList
概述 ArrayList 是 List 接口的一个实现类,也是 Java 中最常用的容器实现类之一,可以把它理解为「可变数组」. 我们知道,Java 中的数组初始化时需要指定长度,而且指定后不能改变. ...
- CSS开启硬件加速来提高网站性能
原文永久链接 CSS animations, transforms 以及 transitions 不会自动开启GPU加速,而是由浏览器的缓慢的软件渲染引擎来执行. 那我们怎样才可以切换到GPU模式呢, ...
- Vmware Exsi使用简要说明
界面介绍 Exsi的管理工具可以用vSphere Client来管理虚拟机.管理虚拟的网络交换机.管理物理机的内存.物理机的硬盘.物理机的CPU等资源.界面的大致介绍如下图. 资源分配 创建内存.CP ...
- Vue组件间通信-Vuex
上回说到Vue组件间通讯,最后留了一个彩蛋~~~Vuex.Vuex是另一种组件通讯的方法,这节来说说Vuex(store仓库). 首先Vuex需要安装,安装的方式有很多,在这里就不一一细说了.我是通过 ...
- CentOS7 安装 单机 Mysql
1.解压文件 [root@centos3 ~]# tar -zxvf mysql-5.7.19-linux-glibc2.12-x86_64.tar.gz -C /usr/local/ 2.重命名 [ ...
- Mysql无法启动情况下,如何恢复数据?
本文适用于,mysql无法启动,但数据文件未丢失的情况. Mysql因意外情况,导致无法启动,数据库未做备份的情况下,如何将数据迁移至其他数据库中. 原数据库地址:192.168.1.100(以下简称 ...
- 【Java例题】6.1 进制转换
1.进制转换.输入一个某种进制的整数,将其转换为其它进制的整数.说明:仅考虑十.二.八和十六进制. package chapter6; import java.util.*; public class ...