SQL Server2005使用CTE实现递归
本文来自:http://www.cnblogs.com/wenjl520/archive/2010/01/18/1650393.html
CTE递归原理:
递归CTE是由两个最小查询构建的.第一个是定位成员(Anchor Member,AM),它是一个非递归查询,第二个是递归成员(Recursive Member,RM),它是递归查询.在CTE括号中(AS 子句之后),定义独立查询或引用回相同CTE的查询,AM与RM由UNION ALL语句分隔.AM紧被调用一次,RM将被重复调用,直到查询不在返回数据行为止.可以使用UNION或UNION ALL运算符彼此追加多个AM,具体取决于是否希望删除重复数据(必须使用UNION ALL运算符来追加递归成员).语法如下:
--需要查询字段集合,也是查询结果的字段集合
WITH SimpleRecursive(filed names)
AS
(
--查询定位成员表
<SELECT Statement for the Anchor Member>
UNION ALL
--查询递归成员表
<SELECT Statement for the Recursive Member>
)
SELECT * FROM SimpleRecursive
实例:我们将创建一个员工表和一个名为ReportsTo的自引用字段,其引用回Emloyee_ID,然后编写一个查询,其返回像Stephen(Employee_ID=2)报告的所有员工以及向Stephen的下属报告的所有员工.
代码清单:
--创建表
CREATE TABLE Employee_Tree
(
Employee_NM NVARCHAR(50) ,
Employee_ID INT PRIMARY KEY ,
ReportsTo INT
) INSERT INTO Employee_Tree
VALUES ( 'Richard', 1, NULL )
INSERT INTO Employee_Tree
VALUES ( 'Stephen', 2, 1 )
INSERT INTO Employee_Tree
VALUES ( 'Clemens', 3, 2 )
INSERT INTO Employee_Tree
VALUES ( 'Malek', 4, 2 )
INSERT INTO Employee_Tree
VALUES ( 'Goksin', 5, 4 )
INSERT INTO Employee_Tree
VALUES ( 'Kimberly', 6, 1 )
INSERT INTO Employee_Tree
VALUES ( 'Ramesh', 7, 5 )
--创建递归查询
WITH SimpleRecursive ( Employee_NM, Employee_ID, ReportsTo )
AS ( SELECT Employee_NM ,
Employee_ID ,
ReportsTo
FROM Employee_Tree
WHERE Employee_ID = 2
UNION ALL
SELECT p.Employee_NM ,
p.Employee_ID ,
p.ReportsTo
FROM Employee_Tree p
INNER JOIN SimpleRecursive A ON A.Employee_ID = p.ReportsTo
)
SELECT sr.Employee_ID AS empid ,
sr.Employee_NM AS Emp ,
et.Employee_NM AS Boss
FROM SimpleRecursive sr
INNER JOIN Employee_Tree et ON sr.ReportsTo = et.Employee_ID
查询结果:

递归过程开始于Employee_ID=2的位置(定义成员或第一个SELECT).它获取该记录,并使用递归递归成员(UNION ALL之后的SELECT)获取所有向Stephen报告的记录以及该记录的子记录.(Goksin向Malek报告,Malek向Stephen报告).每一个后续递归都尝试找到更多的子记录.它们以先前递归已经找到的员工作为父记录.最终该递归不返回结果,这是导致递归停止的原因(为什么没有返回Kimberly的原因).如果该定位成员被改变成Employee_ID=1,则Kimberly也将在结果中被返回.
根据设计,递归成员将一直查找子记录,并可以无限循环.如果您怀疑将会进行许多循环,并希望限制递归调用次数,可以使用OPTION子句在外部查询的后面指定MAXRECURSION选项.
OPTION(MAXRECURSION 25)
这一选项将使sql server2005在cte出现指定限制时产生一条错误.默认情况下,限制为100(即省略该选项时).要不想指定选项.必须将MAXRECURSION设为0.
代码清单:
WITH SimpleRecursive ( Employee_NM, Employee_ID, ReportsTo )
AS ( SELECT Employee_NM ,
Employee_ID ,
ReportsTo
FROM Employee_Tree
WHERE Employee_ID = 2
UNION ALL
SELECT p.Employee_NM ,
p.Employee_ID ,
p.ReportsTo
FROM Employee_Tree p
INNER JOIN SimpleRecursive A ON A.Employee_ID = p.ReportsTo
)
SELECT sr.Employee_ID AS empid ,
sr.Employee_NM AS Emp ,
et.Employee_NM AS Boss
FROM SimpleRecursive sr
INNER JOIN Employee_Tree et ON sr.ReportsTo = et.Employee_ID
OPTION(MAXRECURSION 2)
结果如下:

还会看到以下错误:
消息 530,级别 16,状态 1,第 1 行
语句被终止。完成执行语句前已用完最大递归 2。
一种可以避免出现此异常的方法是使用一个所产生的列来跟踪所在的级别,并包含在WHERE子句中,而不是MAXRECURSION.以下结果与上一示例相同,但不产生错误.
代码清单:
WITH SimpleRecursive ( Employee_NM, Employee_ID, ReportsTo ,Sublevel)
AS ( SELECT Employee_NM ,
Employee_ID ,
ReportsTo,
0
FROM Employee_Tree
WHERE Employee_ID = 2
UNION ALL
SELECT p.Employee_NM ,
p.Employee_ID ,
p.ReportsTo,
Sublevel + 1
FROM Employee_Tree p
INNER JOIN SimpleRecursive A ON A.Employee_ID = p.ReportsTo
)
SELECT sr.Employee_ID AS empid ,
sr.Employee_NM AS Emp ,
et.Employee_NM AS Boss
FROM SimpleRecursive sr
INNER JOIN Employee_Tree et ON sr.ReportsTo = et.Employee_ID
WHERE Sublevel <=2
ok,CTE递归查询完成了.
如果标题未标有<转载、转>等字则属于作者原创,欢迎转载,其版权归作者和博客园共有。
作 者:温景良
文章出处:http://wenjl520.cnblogs.com/ 或 http://www.cnblogs.com/
SQL Server2005使用CTE实现递归的更多相关文章
- SQL Server 公用表表达式(CTE)实现递归
公用表表达式简介: 公用表表达式 (CTE) 可以认为是在单个 SELECT.INSERT.UPDATE.DELETE 或 CREATE VIEW 语句的执行范围内定义的临时结果集.CTE 与派生表类 ...
- SQL Server 公用表表达式(CTE)实现递归的方法
公用表表达式简介: 公用表表达式 (CTE) 可以认为是在单个 SELECT.INSERT.UPDATE.DELETE 或 CREATE VIEW 语句的执行范围内定义的临时结果集.CTE 与派生表类 ...
- SQL点点滴滴_公用表表达式(CTE)递归的生成帮助数据
本文的作者辛苦了,版权问题特声明本文出处:http://www.cnblogs.com/wy123/p/5960825.html 工作有时候会需要一些帮助数据,必须需要连续的数字,连续间隔的时间点,连 ...
- sql server使用公用表表达式CTE通过递归方式编写通用函数自动生成连续数字和日期
问题:在数据库脚本开发中,有时需要生成一堆连续数字或者日期,例如yearly report就需要连续数字做年份,例如daily report就需要生成一定时间范围内的每一天日期.而自带的系统表mast ...
- SQL Server封闭掉 触发器递归
SQL Server关闭掉 触发器递归SQL Server 是有一个开关, 可以关闭掉 触发器递归的.EXEC sp_dboption '数据库名字', 'recursive triggers', ...
- 在WinCC中通过VBS操作SQL Server2005
在项目中需要在一定条件满足时,保存一些数据到数据库中,并可根据条件查询.考虑到WinCC6.2以后采用的就是SQL Server2005数据库,所以直接利用该数据库即可,通过SQL Server Ma ...
- java连接sql server2005
转自:http://blog.sina.com.cn/s/blog_889b58310100zqyz.html 一:配置 第一步:在网上下载SQLServer2005的驱动包 http://www.m ...
- 公用表表达式(CTE)递归的生成帮助数据
本文的作者辛苦了,版权问题特声明本文出处:http://www.cnblogs.com/wy123/p/5960825.html 工作有时候会需要一些帮助数据,必须需要连续的数字,连续间隔的时间点,连 ...
- SQL Server2005索引碎片分析和解决方法
SQL Server2005索引碎片分析和解决方法 本文作者(郑贤娴),请您在阅读本文时尊重作者版权. 摘要: SQL Server,为了反应数据的更新,需要维护表上的索引,因而这些索引会形成碎片.根 ...
随机推荐
- PHP获取中英文混合字符串长度及截取
1.字符串长度 PHP获取中英文混合字符串长度的实现代码如下,1中文=1位,2英文=1位,可自行修改 /** * PHP获取字符串中英文混合长度 * @param $str string 字符串 * ...
- Func 委托 和 Action 委托 初步谈论
继上篇EventHandler之后,继续填坑,简单了解下Func<TResult> 委托 和 Action 委托. msdn对于两者的解释: Func<TResult>:封装一 ...
- 自适应SimpsonSimpson积分
- SQL Server -SET ANSI_NULLS
当ANSI_NULLS 为ON时,遵循SQL92的标准,只能使用IS NULL 来判断值是否为NULL, 而不能使用=或<>来与NULL做比较,任何值包括NULL值与NULL值做=或< ...
- UVA11361 Investigating Div-Sum Property(数位dp)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud 题目意思:问在区间[A,B]有多少个数不仅满足自身是k的倍数,而且其各个位数上的和 ...
- 从C到C++的升级
C++的语言类型 C++是静态的强类型语言. 静态语言:数据类型在编译期间检查,因此在写程序时需要声明变量的类型 强类型语言:强调数据类型,不同的数据类型间的转换需要进行强制类型转换 C与C++的关系 ...
- php 出现 500 Internal Server Error错误问题解决
set_time_limit(0); //设置超时时间 chmod 777 filename //设置文件权限 问题根本不在这,读取数据太多,数组是很站内存的. 内存设置大些就ok了 ini_set( ...
- 序列化layer创建的弹出表单并ajax提交
/** *createTime:2015-09-13 *updateTime:2015-09-13 *author:刘俊 *phone:13469119119 *QQ:418873053 **/ va ...
- js戳和php戳时间换算
问题:剩余多少时间,如果只用php来输出,却看不到动态效果.解决办法,利用获取的时间减去当前时间js 时间格式转换php时间商品距离秒杀时间的天数时分秒<input name="tes ...
- [Head First Python]5. 推导数据:处理数据
读取4个文件内容,格式化数据,升序,显示每个文件前3个数据 julie.txt 2.59,2.11,2:11,2:23,3-10,2-23,3:10,3.21,3-21 james.txt 2-34, ...