(转)使用公用表表达式的递归查询(SQLSERVER2005)

本文涉及的产品
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
云数据库 RDS SQL Server,基础系列 2核4GB
简介: 在 SQL Server 2005 中,当某个查询引用递归 CTE 时,它即被称为“递归查询”。递归查询通常用于返回分层数据,例如:显示某个组织图中的雇员或物料清单方案(其中父级产品有一个或多个组件,而那些组件可能还有子组件,或者是其他父级产品的组件)中的数据。

公用表表达式 (CTE) 具有一个重要的优点,那就是能够引用其自身,从而创建递归 CTE。递归 CTE 是一个重复执行初始 CTE 以返回数据子集直到获取完整结果集的公用表表达式。


在 SQL Server 2005 中,当某个查询引用递归 CTE 时,它即被称为“递归查询”。递归查询通常用于返回分层数据,例如:显示某个组织图中的雇员或物料清单方案(其中父级产品有一个或多个组件,而那些组件可能还有子组件,或者是其他父级产品的组件)中的数据。


递归 CTE 可以极大地简化在 SELECT、INSERT、UPDATE、DELETE 或 CREATE VIEW 语句中运行递归查询所需的代码。在 SQL Server 的早期版本中,递归查询通常需要使用临时表、游标和逻辑来控制递归步骤流。有关公用表表达式的详细信息,请参阅使用公用表表达式。


递归 CTE 的结构


Transact-SQL 中的递归 CTE 的结构与其他编程语言中的递归例程相似。尽管其他语言中的递归例程返回标量值,但递归 CTE 可以返回多行。


递归 CTE 由下列三个元素组成:


1.例程的调用。


递归 CTE 的第一个调用包括一个或多个由 UNION ALL、UNION、EXCEPT 或 INTERSECT 运算符联接的 CTE_query_definitions。由于这些查询定义形成了 CTE 结构的基准结果集,所以它们被称为“定位点成员”。


CTE_query_definitions 被视为定位点成员,除非它们引用了 CTE 本身。所有定位点成员查询定义必须放置在第一个递归成员定义之前,而且必须使用 UNION ALL 运算符联接最后一个定位点成员和第一个递归成员。



2.例程的递归调用。


递归调用包括一个或多个由引用 CTE 本身的 UNION ALL 运算符联接的 CTE_query_definitions。这些查询定义被称为“递归成员”。



3.终止检查。


终止检查是隐式的;当上一个调用中未返回行时,递归将停止。




注意:


如果递归 CTE 组合不正确,可能会导致无限循环。例如,如果递归成员查询定义对父列和子列返回相同的值,则会造成无限循环。在测试递归查询的结果时,可以通过在 INSERT、UPDATE、DELETE 或 SELECT 语句的 OPTION 子句中使用 MAXRECURSION 提示和 0 到 32,767 之间的值,来限制特定语句允许的递归级数。有关详细信息,请参阅查询提示 (Transact-SQL) 和 WITH common_table_expression (Transact-SQL)。



伪代码和语义


递归 CTE 结构必须至少包含一个定位点成员和一个递归成员。以下伪代码显示了包含一个定位点成员和一个递归成员的简单递归 CTE 的组件。


WITH cte_name ( column_name [,...n] )
AS
(
CTE_query_definition –- Anchor member is defined.
UNION ALL
CTE_query_definition –- Recursive member is defined referencing cte_name.
)
-- Statement using the CTE
SELECT *
FROM cte_name


递归执行的语义如下:


1.将 CTE 表达式拆分为定位点成员和递归成员。



2.运行定位点成员,创建第一个调用或基准结果集 (T0)。



3.运行递归成员,将 Ti 作为输入,将 Ti+1 作为输出。



4.重复步骤 3,直到返回空集。



5.返回结果集。这是对 T0 到 Tn 执行 UNION ALL 的结果。


示例


以下示例通过返回 Adventure Works Cycles 公司的雇员的分层列表(从最高级雇员开始)显示递归 CTE 结构的语义。执行 CTE 的语句将结果集限制到研发组中的雇员。示例后面是代码执行的演练。



复制代码


USE AdventureWorks;GOWITH DirectReports (ManagerID, EmployeeID, Title, DeptID, Level)AS(-- Anchor member definition SELECT e.ManagerID, e.EmployeeID, e.Title, edh.DepartmentID, 0 AS Level FROM HumanResources.Employee AS e INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh ON e.EmployeeID = edh.EmployeeID AND edh.EndDate IS NULL WHERE ManagerID IS NULL UNION ALL-- Recursive member definition SELECT e.ManagerID, e.EmployeeID, e.Title, edh.DepartmentID, Level + 1 FROM HumanResources.Employee AS e INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh ON e.EmployeeID = edh.EmployeeID AND edh.EndDate IS NULL INNER JOIN DirectReports AS d ON e.ManagerID = d.EmployeeID)-- Statement that executes the CTESELECT ManagerID, EmployeeID, Title, LevelFROM DirectReportsINNER JOIN HumanResources.Department AS dp ON DirectReports.DeptID = dp.DepartmentIDWHERE dp.GroupName = N'Research and Development' OR Level = 0;GO


示例代码演练



1.递归 CTE DirectReports 定义了一个定位点成员和一个递归成员。



2.定位点成员返回基准结果集 T0。这就是公司中的最高级雇员,即不向经理报告的雇员。


以下是定位点成员返回的结果集:



复制代码


ManagerID EmployeeID Title Level--------- ---------- --------------------------------------- ------NULL 109 Chief Executive Officer 0



3.递归成员返回定位点成员结果集中的雇员的直接下属。这是通过在 Employee 表和 DirectReports CTE 之间执行联接操作获得的。正是此次对 CTE 自身的引用建立了递归调用。利用 CTE DirectReports 中的雇员作为输入 (Ti),联接 (Employee.ManagerID = DirectReports.EmployeeID) 返回经理为 (Ti) 的雇员作为输出 (Ti+1)。这样,递归成员的第一次迭代返回了以下结果集:



复制代码


ManagerID EmployeeID Title Level--------- ---------- --------------------------------------- ------109 12 Vice President of Engineering 1



4.重复激活递归成员。递归成员的第二次迭代使用步骤 3 中的单行结果集(包含 EmployeeID 12)作为输入值,并返回以下结果集:



复制代码


ManagerID EmployeeID Title Level--------- ---------- --------------------------------------- ------12 3 Engineering Manager 2


递归成员的第三次迭代使用上面的单行结果集(包含 EmployeeID 3))作为输入值,并返回以下结果集:



复制代码


ManagerID EmployeeID Title Level--------- ---------- --------------------------------------- ------3 4 Senior Tool Designer 33 9 Design Engineer 33 11 Design Engineer 33 158 Research and Development Manager 33 263 Senior Tool Designer 33 267 Senior Design Engineer 33 270 Design Engineer 3


递归成员的第四次迭代使用 EmployeeID 值 4、9、11、158、263、267 和 270 的上一个行集作为输入值。


重复此过程,直到递归成员返回一个空结果集。



5.正在运行的查询返回的最终结果集是定位点成员和递归成员生成的所有结果集的并集。


以下是示例返回的完整结果集:



复制代码


ManagerID EmployeeID Title Level--------- ---------- --------------------------------------- ------NULL 109 Chief Executive Officer 0109 12 Vice President of Engineering 112 3 Engineering Manager 23 4 Senior Tool Designer 33 9 Design Engineer 33 11 Design Engineer 33 158 Research and Development Manager 33 263 Senior Tool Designer 33 267 Senior Design Engineer 33 270 Design Engineer 3263 5 Tool Designer 4263 265 Tool Designer 4158 79 Research and Development Engineer 4158 114 Research and Development Engineer 4158 217 Research and Development Manager 4(15 row(s) affected)

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
相关文章
|
6月前
|
SQL
sql server链接查询
sql server链接查询
|
6月前
|
SQL
sql server简单查询
sql server简单查询
|
11月前
|
SQL 数据库
SQL Server 连接查询和子查询
SQL Server 连接查询和子查询
147 0
|
1月前
|
SQL 存储 数据挖掘
SQL Server 日期格式查询详解
SQL Server 日期格式查询详解
160 2
|
3月前
|
SQL Java 数据库
jsp中使用Servlet查询SQLSERVER数据库中的表的信息,并且打印在屏幕上
该博客文章介绍了在JSP应用中使用Servlet查询SQL Server数据库的表信息,并通过JavaBean封装图书信息,将查询结果展示在Web页面上的方法。
jsp中使用Servlet查询SQLSERVER数据库中的表的信息,并且打印在屏幕上
|
3月前
|
SQL Java 数据库连接
JDBC连接SQL Server2008 完成增加、删除、查询、修改等基本信息基本格式及示例代码
这篇文章提供了使用JDBC连接SQL Server 2008数据库进行增加、删除、查询和修改操作的基本步骤和示例代码。
|
3月前
|
SQL 存储 安全
Play Framework的安全面纱:揭开隐藏在优雅代码下的威胁
【8月更文挑战第31天】Play Framework 是一款高效、轻量级的 Web 开发框架,内置多种安全特性,助力开发者构建安全稳定的应用。本文详细介绍 Play 如何防范 SQL 注入、XSS 攻击、CSRF 攻击,并提供安全的密码存储方法及权限管理策略,通过具体示例代码展示实施步骤,助您有效抵御常见威胁。
64 0
|
3月前
|
SQL 存储 开发框架
Entity Framework Core 与 SQL Server 携手,高级查询技巧大揭秘!让你的数据操作更高效!
【8月更文挑战第31天】Entity Framework Core (EF Core) 是一个强大的对象关系映射(ORM)框架,尤其与 SQL Server 数据库结合使用时,提供了多种高级查询技巧,显著提升数据操作效率。它支持 LINQ 查询,使代码简洁易读;延迟加载与预先加载机制优化了相关实体的加载策略;通过 `FromSqlRaw` 或 `FromSqlInterpolated` 方法支持原始 SQL 查询;可调用存储过程执行复杂任务;利用 `Skip` 和 `Take` 实现分页查询,便于处理大量数据。这些特性共同提升了开发者的生产力和应用程序的性能。
177 0
|
4月前
|
SQL 关系型数据库 数据库
关系型数据库SQLserver查询数据
【7月更文挑战第28天】
47 4
|
4月前
|
SQL 关系型数据库
关系型数据库SQLserver查询编辑器
【7月更文挑战第27天】
52 3
下一篇
无影云桌面