T_SQL语言递归查询
sql server 递归查询父级字段-概述说明以及解释
sql server 递归查询父级字段-概述说明以及解释1.引言1.1 概述概述部分的内容可以从以下几个方面展开:首先,简要介绍递归查询的概念。
递归查询是指在数据库中通过反复执行相同的查询操作,从而获取多层次关系数据的一种查询方式。
递归查询常用于父子关系数据的处理,比如组织结构、分类层级等。
其次,说明递归查询的重要性和实际应用场景。
在实际的数据操作中,很多时候需要查询某个节点的所有上级或者下级节点,而递归查询正是解决这类问题的有效方式。
递归查询可以帮助我们实现更高效的数据处理和管理,提高数据的可用性和灵活性。
然后,提及本文将要介绍的内容。
本文主要讨论在SQL Server 数据库中如何进行递归查询父级字段的操作。
首先将介绍递归查询的原理和概念,然后具体介绍SQL Server 中的递归查询实现方式。
最后,强调本文的目的和意义。
通过深入研究和理解递归查询父级字段的相关知识,读者可以更加灵活地处理和管理数据库中的父子关系数据,提升数据处理效率和准确性。
同时,本文也为读者提供了解决类似问题的实际操作指导,帮助读者在实际工作中快速解决相关的数据查询和处理任务。
1.2文章结构1.2 文章结构本文将围绕SQL Server中递归查询父级字段展开进行介绍。
文章主要包括三个部分:第一部分是引言,将对递归查询和父级字段的概念进行概述。
我们会介绍递归查询的原理以及其在数据库领域中的重要性。
同时,我们也会简要介绍本文的结构和目的,以帮助读者了解文章的整体框架。
第二部分是正文,将详细介绍SQL Server中实现递归查询的方式。
我们会探讨不同的递归查询方法,并深入讨论它们的实现原理和适用场景。
通过这一部分的学习,读者将对如何在SQL Server中使用递归查询来处理父级字段有一个全面的了解。
第三部分是结论,我们将重点探讨递归查询在父级字段中的应用。
我们会通过实际案例和示例来说明如何利用递归查询来处理具有父子关系的数据,并分析其优缺点和适用性。
sql语句递归查询使用注意事项
sql语句递归查询使用注意事项
1. 定义正确的递归条件:递归查询通常包含一个基本查询和一个递归查询。
基本查询用于获取初始数据,而递归查询用于获取与初始数据相关的更多数据。
在递归查询中,必须明确定义递归终止的条件,否则可能导致无限递归。
2. 使用适当的连接条件和过滤条件:递归查询通常需要指定连接条件和过滤条件,以确保查询结果与预期一致。
连接条件用于连接基本查询和递归查询的结果集,过滤条件用于限制递归查询的结果。
3. 考虑性能问题:递归查询可能涉及大量的数据和多次查询,因此性能是一个重要的考虑因素。
为了提高性能,可以使用索引、优化查询语句、使用临时表等技术。
4. 避免循环引用:在递归查询中,如果存在循环引用的情况,可能导致查询结果不准确或查询失败。
为了避免循环引用,可以使用限制递归深度的策略。
5. 注意数据完整性:递归查询可能导致无效或重复的数据,因此在编写递归查询语句时需要考虑数据完整性。
可以使用约束、触发器或其他数据验证机制来确保数据的完整性。
6. 适当使用递归查询:递归查询是强大的工具,但并不适用于所有情况。
在使用递归查询之前,需要仔细评估应用场景,确保递归查询是解决问题的最佳方法。
sqlserver中递归写法
sqlserver中递归写法
递归分两种:⼀种由⽗项向下级递归,另⼀种是由⼦项向上级递归。
下⾯就这两种情况做个简单的处理。
假设有⼀个表treeview,包含字段 id,parentid,text 分别代表id,上级id,描述字段(这⾥就不把建表sql写出来了)。
1、由⽗项递归下级
with cte(id,parentid,text)
as
(--⽗项
select id,parentid,text from treeview where parentid = 450 --需替换成⾃⼰希望查询的id
union all
--递归结果集中的下级
select t.id,t.parentid,t.text from treeview as t
inner join cte as c on t.parentid = c.id
)
select id,parentid,text from cte
2、由⼦级递归⽗项
with cte(id,parentid,text)
as
(--下级⽗项
select id,parentid,text from treeview where id = 450 --需替换成⾃⼰希望查询的id
union all
--递归结果集中的⽗项
select t.id,t.parentid,t.text from treeview as t
inner join cte as c on t.id = c.parentid
)
select id,parentid,text from cte
简单的例⼦。
。
sql写递归查询
sql写递归查询递归查询在SQL语言中可以使用`WITH RECURSIVE`语句实现,该语句能够实现在同一个查询中反复引用自身。
为了满足字数不少于6000字的要求,我们将分为以下几个部分来探讨递归查询。
1. 什么是递归查询递归查询是一种在关系型数据库中常用的查询技术,它可以用来在同一个查询中引用自身,从而实现对表或视图中的递归结构进行处理。
2. 递归查询的语法在SQL中,递归查询可以使用`WITH RECURSIVE`语句来定义。
基本语法如下:```sqlWITH RECURSIVE递归查询名称 (递归查询的列名1, 递归查询的列名2, ...)AS (-- 非递归查询非递归查询语句UNION ALL-- 递归查询递归查询语句)-- 最终查询SELECT * FROM 递归查询名称;```其中,递归查询语句中可以引用自身,直到满足递归终止条件为止。
3. 递归查询的应用场景递归查询在关系型数据库中有广泛的应用场景,例如组织架构、文件系统、树形结构等。
在这些场景中,通过递归查询可以方便地处理上下级关系、查询子节点或父节点等需求。
4. 递归查询的例子假设有下面这样一个表`Employee`,其中包含员工的ID、姓名和直属上级的ID。
```sqlCREATE TABLE Employee (ID INT,Name VARCHAR(50),ManagerID INT);INSERT INTO Employee (ID, Name, ManagerID)VALUES(1, 'John', NULL),(2, 'Mary', 1),(3, 'Peter', 1),(4, 'Alice', 2),(5, 'Bob', 3),(6, 'Tom', 4),(7, 'Sara', 5),(8, 'David', 6),(9, 'Lisa', 7),(10, 'Mike', 8);```现在需要查询员工的直属上级以及上级的上级,直到到达根节点为止。
mysql sql语句用递归
mysql sql语句用递归MySQL中并没有内置的递归函数或语句,但可以通过使用存储过程和临时表来实现递归查询。
下面是十个例子,展示了如何使用递归查询来解决不同的问题。
1. 查询树状结构假设有一个表格存储了员工的信息,包括员工ID和上级ID。
我们可以使用递归查询来获取某个员工的所有下级员工,以及他们的下级员工,以此类推。
```sqlCREATE PROCEDURE getSubordinates(IN employeeID INT) BEGINCREATE TEMPORARY TABLE subordinates (employeeID INT, name VARCHAR(255));INSERT INTO subordinates SELECT employeeID, name FROM employees WHERE employeeID = employeeID;REPEATINSERT INTO subordinates SELECT employees.employeeID, FROM employees INNER JOIN subordinates ON employees.supervisorID = subordinates.employeeID;UNTIL ROW_COUNT() = 0 END REPEAT;SELECT * FROM subordinates;END```2. 查询路径假设有一个表格存储了员工的信息,包括员工ID和上级ID。
我们可以使用递归查询来获取某个员工的上级路径,即从他直到最高级别上级的所有员工。
```sqlCREATE PROCEDURE getSupervisorPath(IN employeeID INT) BEGINCREATE TEMPORARY TABLE supervisorPath (employeeID INT, name VARCHAR(255));INSERT INTO supervisorPath SELECT employeeID, name FROM employees WHERE employeeID = employeeID;REPEATINSERT INTO supervisorPath SELECT employees.employeeID, FROM employees INNER JOIN supervisorPath ON employees.employeeID = supervisorPath.supervisorID;UNTIL ROW_COUNT() = 0 END REPEAT;SELECT * FROM supervisorPath;END```3. 查询层级假设有一个表格存储了员工的信息,包括员工ID和上级ID。
sql递归查询树形结构
《sql递归查询树形结构》在许多情况下,我们需要查询具有树形结构的数据,例如在档案管理、项目管理或电子商务中。
树形结构是一种层次结构,其中每个项都与其父项以及其所有子项相关联。
使用SQL进行递归查询可以轻松获取这些结构中的所有信息。
一、了解SQL递归查询SQL递归查询是一种强大的工具,用于在数据库中查询具有嵌套关系的记录。
通过使用WITH RECURSIVE语句,我们可以模拟递归过程,从而获取整个树形结构的数据。
二、创建递归查询下面是一个基本的递归查询示例,用于从数据库中检索具有树形结构的档案记录。
```sqlWITH RECURSIVE recursive_query AS (SELECT id, name, parent_idFROM categories -- 替换为你的表名WHERE parent_id IS NULL -- 根节点UNION ALLSELECT c.id, , c.parent_idFROM categories cINNER JOIN recursive_query r ON c.parent_id = r.id -- 连接子节点)SELECT * FROM recursive_query;```上述查询首先选择根节点(没有父节点的记录),然后通过连接子节点来逐步扩展查询结果。
递归过程会一直进行,直到没有更多的子节点为止。
三、使用递归查询的注意事项1. 确保表结构支持递归查询:确保你的数据库表具有适当的列来存储父级关系信息。
通常,使用一个外键关联记录与其父级记录。
2. 合理设置递归深度:递归查询可能会对性能产生影响,特别是对于大型数据集。
确保根据你的需求合理设置递归深度,避免过度消耗资源。
3. 避免无限循环:在某些情况下,可能存在具有无限嵌套关系的记录。
确保在编写递归查询时考虑到这种情况,并采取适当的措施避免无限循环。
四、其他技巧和扩展1. 使用CTE(公共表表达式)代替WITH RECURSIVE语句:CTE是另一种创建递归查询的方法,语法上略有不同,但功能类似。
PostgreSQL中RECURSIVE递归查询使用总结
PostgreSQL中RECURSIVE递归查询使⽤总结RECURSIVE前⾔WITH提供了⼀种⽅式来书写在⼀个⼤型查询中使⽤的辅助语句。
这些语句通常被称为公共表表达式或CTE,它们可以被看成是定义只在⼀个查询中存在的临时表。
在WITH⼦句中的每⼀个辅助语句可以是⼀个SELECT、INSERT、UPDATE或DELETE,并且WITH⼦句本⾝也可以被附加到⼀个主语句,主语句也可以是SELECT、INSERT、UPDATE或DELETE。
CTE or WITHWITH语句通常被称为通⽤表表达式(Common Table Expressions)或者CTEs。
WITH语句作为⼀个辅助语句依附于主语句,WITH语句和主语句都可以是SELECT,INSERT,UPDATE,DELETE中的任何⼀种语句。
举个栗⼦WITH result AS (SELECT er_idFROM documents dGROUP BY er_id),info as(SELECT t.*,json_build_object('id', ur.id, 'name', ) AS user_infoFROM result tLEFT JOIN users ur on ur.id = er_idWHERE ur.id IS NOT NULL)select * from info定义了两个WITH辅助语句,result和info。
result查询出符合要求的user信息,然后info对这个信息进⾏组装,组装出我们需要的数据信息。
当然不⽤这个也是可以的,不过CTE主要的还是做数据的过滤。
什么意思呢,我们可以定义多层级的CTE,然后⼀层层的查询过滤组装。
最终筛选出我们需要的数据,当然你可能会问为什么不⼀次性拿出所有的数据呢,当然如果数据很⼤,我们通过多层次的数据过滤组装,在效率上也更好。
在WITH中使⽤数据修改语句WITH中可以不仅可以使⽤SELECT语句,同时还能使⽤DELETE,UPDATE,INSERT语句。
pgsql递归查询的运行流程
pgsql递归查询的运行流程
递归查询是一种查询策略,用于在关系数据库中查询层次结构数据。
在PostgreSQL中,递归查询通常使用WITH RECURSIVE子句来实现。
递归查询的运行流程如下:
1. 解析查询语句:数据库系统首先解析查询语句,并识别出其中的WITH RECURSIVE子句。
2. 创建临时表:根据WITH RECURSIVE子句中的递归部分定义,数据库系统创建一个临时表,在该表中存储递归查询的结果。
3. 初始化递归:数据库系统将WITH RECURSIVE子句中的初始查询部分执行一次,将结果插入到临时表中。
4. 递归迭代:从临时表中取出上一次迭代的结果作为输入,执行递归部分的查询,将结果插入到临时表中。
不断重复这一步骤,直到递归查询不再返回结果。
5. 返回结果:最后,数据库系统将临时表中的结果返回给用户。
总结起来,递归查询的运行流程可以简化为初始化、迭代和返回结果三个步骤。
在每一次迭代中,数据库系统将上一次迭代的结果作为输入,执行递归查询的部分,将结果插入到临时表中。
这样,递归查询就可以不断地通过迭代来获取所有层次结构数据。
sql递归解析
sql递归解析SQL递归是一种强大的技术,可以在关系型数据库中处理层次结构的数据。
通过使用递归,我们可以轻松地解析和处理复杂的数据结构。
让我们来看一下递归是如何工作的。
递归是指在一个函数中调用自身的过程。
在SQL中,我们可以使用递归来处理具有层次结构的数据,例如组织结构、文件目录等。
为了更好地理解递归的工作原理,我们可以以一个简单的例子开始。
假设我们有一个包含员工和他们的上级关系的表。
我们可以使用递归来查找某个员工的所有下属。
我们需要定义一个递归查询。
在这个查询中,我们将指定初始条件,然后使用递归调用来迭代地查找下属。
在每次迭代中,我们将使用上一次迭代的结果作为输入,并继续向下查找下属。
下面是一个示例查询,用于查找员工A的所有下属:WITH RECURSIVE employee_hierarchy AS (SELECT employee_id, employee_name, manager_idFROM employeesWHERE employee_name = 'A'UNION ALLSELECT employees.employee_id, employees.employee_name,employees.manager_idFROM employeesJOIN employee_hierarchy ON employees.manager_id = employee_hierarchy.employee_id)SELECT * FROM employee_hierarchy;在这个查询中,我们首先选择初始条件为员工名为'A'的记录。
然后,我们使用递归调用来选择所有员工的下属。
这个过程将一直持续到没有更多的下属为止。
通过使用递归查询,我们可以轻松地解析和处理具有层次结构的数据。
这种技术在许多场景中非常有用,例如组织结构的管理、文件目录的处理等。
总结一下,SQL递归是一种强大的技术,可以用于处理具有层次结构的数据。
层级查询sql语句
层级查询sql语句层级查询是指在关系型数据库中,通过使用SQL语句来对多个表进行关联查询,从而获取具有层级结构的数据。
层级查询常用于处理树状结构的数据,如组织架构、分类目录等。
下面列举了十个常见的层级查询SQL语句示例。
1. 查询某个节点的所有子节点```sqlSELECT * FROM 表名 WHERE 父节点ID = '节点ID';```这个语句用于查询指定节点下的所有子节点,可以通过将节点ID替换为具体的节点ID来获取对应节点的子节点。
2. 查询某个节点的所有父节点```sqlWITH RECURSIVE cte AS (SELECT * FROM 表名 WHERE 节点ID = '节点ID'UNION ALLSELECT t.* FROM 表名 t INNER JOIN cte ON t.节点ID = cte.父节点ID)SELECT * FROM cte;```这个语句使用了CTE(公用表表达式)和递归查询的方法,可以查询指定节点的所有父节点,可以通过将节点ID替换为具体的节点ID来获取对应节点的父节点。
3. 查询某个节点的所有兄弟节点```sqlSELECT * FROM 表名WHERE 父节点ID = (SELECT 父节点ID FROM 表名 WHERE 节点ID = '节点ID');```这个语句用于查询指定节点的所有兄弟节点,可以通过将节点ID替换为具体的节点ID来获取对应节点的兄弟节点。
4. 查询某个节点的所有祖先节点和后代节点```sqlWITH RECURSIVE cte AS (SELECT * FROM 表名 WHERE 节点ID = '节点ID'UNION ALLSELECT t.* FROM 表名t INNER JOIN cte ON t.父节点ID = cte.节点IDUNION ALLSELECT t.* FROM 表名 t INNER JOIN cte ON t.节点ID = cte.父节点ID)SELECT * FROM cte;```这个语句使用了CTE和递归查询的方法,可以查询指定节点的所有祖先节点和后代节点,可以通过将节点ID替换为具体的节点ID来获取对应节点的祖先节点和后代节点。
transact-sql用法
transact-sql用法Transact-SQL(T-SQL)是一种由Microsoft开发的SQL语言扩展,用于管理和操作Microsoft SQL Server数据库系统。
T-SQL用于执行各种数据库操作,例如创建、修改和删除数据库对象、插入、更新和删除数据、查询和分析数据等。
以下是一些常见的Transact-SQL用法:1.创建数据库对象:使用T-SQL可以创建数据库表、视图、存储过程、函数、触发器等数据库对象。
例如,可以通过CREATE TABLE语句创建表,CREATE VIEW语句创建视图,CREATE PROCEDURE语句创建存储过程等。
2.数据操作:使用T-SQL可以执行各种数据操作,例如插入数据、更新数据和删除数据。
INSERT INTO语句用于插入新的行,UPDATE语句用于更新现有的行,DELETE语句用于删除行。
3.数据查询:使用T-SQL可以执行数据查询操作,以检索所需的数据。
SELECT语句用于查询数据,可以使用WHERE子句过滤数据,使用JOIN子句连接多个表,使用GROUP BY子句对数据进行分组,使用ORDER BY子句进行排序等。
4.事务管理:T-SQL支持事务处理,通过使用BEGIN TRANSACTION、COMMIT和ROLLBACK语句来实现。
这使得可以对一组数据库操作进行原子性的处理,要么全部成功,要么全部失败。
5.错误处理:使用TRY-CATCH块来捕获和处理异常错误。
TRY块中的代码执行,如果发生错误,则控制流将转到CATCH块,并执行适当的错误处理逻辑。
6.存储过程和函数:使用T-SQL可以创建和执行存储过程和函数。
存储过程是一组预定义的SQL语句,可用于执行重复性的任务,并可以接受参数和返回结果。
函数是一种特殊类型的存储过程,它返回一个值。
拓展:除了以上提到的常见用法,T-SQL还提供了很多高级功能,例如使用分析函数(如RANK、LEAD和LAG)进行数据分析,使用窗口函数进行滚动计算,使用递归查询处理层次数据等。
sql语句递归查询(startwith)
sql语句递归查询(startwith)在做项⽬中遇到⼀个问题,就是同⼀个表中的数据存在级联关系,但是只要查出来的末级数据,纠结了好久,好不容易找到了⼀个博主的分享,在这⾥做个记录,也是和⼤家⼀起分享学习⼀下这位⼤神的技术,共勉写代码时碰到要弄清楚Oracle的role之间的传递关系,就是有role A的话,可以通过grant A to B,把A赋予给B,⼜通过grant B to C .那我想知道所有role中,有哪些role具有A的权限.上⽹⼀查发现有个递归查询,不过都讲的不是太详细,⽽那Oracle整的那⽤法实在太怪异了,跟我们平时⽤的SQL差的太远,所以琢磨了好⼀阵⼦脑⼦才转过弯呢.树形结构可能⼀看到递归查询这样太专业的名词⼤家就迷糊了.实际上可以看成有⼀个树形结构,然后我们要怎么把所有树的所有结点查找出来.学数据结构的时候我们知道要遍历⼀个树结构有啥前序遍历,中序遍历,后序遍历.反正挺⿇烦的.不像遍历个数组那么容易的.那实际上在Oracle的⼀个表中也可以保存树形结构信息.你要查询所有的树节点,⾃⼰整个函数或存储过程去整肯定是超级⿇烦的.Oracle提供了⼀个简单的机制帮助你.要⽤到start with ...connect by等关键字.先来假定有下⾯这样⼀个简单的树形结构存储在表中.create table Tree(son char(10), father char(10)); 然后插⼊些信息变成这样的表SON FATHTER孙⼦SB ⼉⼦孙⼦NB ⼉⼦⼉⼦爸爸爸爸爷爷很显然这是⼀个简单的树形结构 ---------孙⼦SB | ^ | |爷爷 --> 爸爸 --> ⼉⼦ -->孙⼦NB递归查询假如要查询出以爷爷为根的树的所有节点值咋整呢 ?如果数据少多来⼏个where嵌套就⾏.但要是树层次有⼏百那会搞死⼈了啊.于是我们就⽤Oracle提供的递归查询.先看下SQL的写法然后再讲解SELECT son FROM treeSTART WITH father = '爷爷'CONNECT BY PRIOR son = father;返回的结果为爸爸⼉⼦孙⼦NB 孙⼦SB代码看起来很短,但是极为怪异,脑⼦半天都不容易转过弯呢.实际上我们不把这个SQL语句跟⼀般的SQL类⽐,⽽把它当作给⼀些函数指定⼀些参数的赋值语句才更容易理解.那怎么来理解上⾯的SQL呢?⾸先把SELECT son FROM tree还是看成⼀般sql⼀样,就是要查找son这⼀列的信息.⽽把以START WITH开头的后⾯所有东东看成⼀个where限制条件.其中START WITH 是指定树的根,这⾥指定的根是 '爷爷',实际上你还可以指定多个根的,⽐如 father in ('爷爷', '爸爸') .⽽CONNECT BY PRIOR son = father相当于表明在递归的过程中,查找到的树中其它节点接着⼜作为根结点.然后继续递归. 反正看这sql语句前先想下树形结构,然后想下⼀般编程语⾔中的递归函数.再来看时就容易理解点.实际上我觉得Oracle这样设计不太好.如果⽤户只是简单的指定的⼀个根节点然后知道树中其他节点信息.那么就直接⽤START WITH指定根就⾏了.CONNECT BY PRIOR显得有点多余,可以不⽤⽤户去指定.当作⼀个默认值,只有需要其他⼀些更复杂的操作时才让⽤户明确指定.这样就不容易误导⼈了.为了便于理解可以可以CONNECT BY那⼀⾏当作多余的,只记住要查询的列名放前⾯,根列名放等号后⾯就⾏.这样只要指定树的根结点就⽐较好理解了.start with ,connect by prior其他变形上⾯讲的⽤START WITH 指定树的根,然后⽤CONNECT BY指定递归条件.是最简单的也是最常⽤的形式.但实际上还有些变形.1.START WITH 可以省略⽐如SELECT son FROM treeCONNECT BY PRIOR son = father;此时不指定树的根的话,就默认把Tree整个表中的数据从头到尾遍历⼀次,每⼀个数据做⼀次根,然后遍历树中其他节点信息.在这个例⼦中,上⾯的SQL等价于SELECT son FROM treeSTART WITH father IN (爷爷,爸爸,⼉⼦,孙⼦NB,孙⼦SB)CONNECT BY PRIOR son = father;那查询到的结果如下,有很多重复信息的爸爸,⼉⼦,孙⼦NB,孙⼦SB ⼉⼦,孙⼦NB,孙⼦SB 孙⼦NB,孙⼦SB2.START WITH 与CONNECT BY PRIOR位置可互换SELECT son FROM treeCONNECT BY PRIOR son = fatherSTART WITH father = '爷爷';这语句与最开头那个是等价的3.nocycle关键字我们知道标准的树结构中是不会有环的,但表中的树形结构不是标准的,有可能导致环的出现⽐如---------孙⼦SB| ^| |爷爷 --> 爸爸 --> ⼉⼦ -->孙⼦NB哎在这⾥想⽤线条整个箭头出来真他妈⿇烦啊.我⼜有点懒不想⽤其他画图⼯具啥的啊.反正假设⼉⼦的⼉⼦是孙⼦SB ,⽽孙⼦SB的⼉⼦是爸爸.这样就形成⼀个环了.当然在Oracle中的role是禁⽌出现循环的.⽐如你grant A to B ,grant B to C .再来个grant C to A会出错的.假如有个上⾯的环,在再使⽤开始的递归查询语⾔会出错.得⽤nocycle关键字指定忽略环.SELECT son FROM treeSTART WITH father = '爷爷'CONNECT BY NOCYCLE PRIOR son = father;此时结果是爸爸⼉⼦孙⼦NB你会注意到由于忽略了环,所以孙⼦SB的信息也被忽略掉了.4. connect by prior 后⾯条件顺序的改变 ()SELECT son FROM treeSTART WITH father = '爷爷'CONNECT BY PRIOR son = father;这是开头的写法,但实际上也可以写成father = son倒过来写.有⼈说没倒过来是从上到下,从根往下.如果倒过来则是从下到上.哎不过我测试了下发现不是那么回事.结果也有点乱七⼋糟的.没想明⽩是啥规律.反正还有待研究啊5.还可以加where条件我上⾯说了可以把start with ,connect 假装看成where 条件⼀样.所以在这个sql语句其他地⽅还可以加其他where 语句,可以看成与递归查询⽆关.只是对整个结果起过滤作⽤⽐如SELECT son FROM tree WHERE son = '孙⼦SB'START WITH father = '爷爷'CONNECT BY PRIOR son = father;当然你不能在最后部分加where,不能在connect by最后⾯再加.。
SQL中实现递归(根据子节点查找父节点)
SQL中实现递归(根据⼦节点查找⽗节点)1,数据库2005之前,使⽤函数实现。
(根据⼦节点查找⽗节点)if object_id('f_getParentBySon') is not null drop function f_getParentBySonGOCREATE function f_getParentBySon(@id varchar(100))RETURNS @t table(id varchar(100))asbegininsert into @t select @idselect @id= Parid from BOM_Detail where id= @id and Parid is not null --第⼀次执⾏,将id=输⼊的id 所在数据全部查出,然后将⽗id赋给变量(⽬的是当同⼀个⼦id参与了多个⽗商品的构造时查出所有的⽗商品)while @@ROWCOUNT > 0begininsert into @t select @id select @id = Parid from BOM_Detail where id= @id and Parid is not null --查询出已经被⽗商品赋值的变量的新数据,并再次将新数据的⽗产品赋给变量进⾏查询,直⾄⽆数据查询跳出循环endreturnendgo使⽤:select a.* from BOM_Detail a , f_getParentBySon('000020000600005') b where a.id= b.id2,数据库2005之后,借助 with as 语句(⽬的仍然是根据⼦节点查找⽗节点);WITH subqry AS(SELECT tb.id, tb.qty, tb.parid FROM tb WHERE id=@idUNION ALLSELECT tb.id, tb.qty, tb.parid FROM tb,subqryWHERE tb.id= subqry.Parid)select * from subqry --查询数据关于with as demo的实例,借助⼤神的⼀篇⽂章。
T-Sql递归查询(给定节点查所有父节点、所有子节点的方法)
T-Sql递归查询(给定节点查所有⽗节点、所有⼦节点的⽅法)-- 查找所有⽗节点with tab as(select Type_Id,ParentId,Type_Name from Sys_ParamType_V2_0 where Type_Id=316--⼦节点union allselect b.Type_Id,b.ParentId,b.Type_Namefromtab a,--⼦节点数据集Sys_ParamType_V2_0 b --⽗节点数据集where a.ParentId=b.Type_Id --⼦节点数据集.parendID=⽗节点数据集.ID)select * from tab;-- 查找所有⼦节点with tab as(select Type_Id,ParentId,Type_Name from Sys_ParamType_V2_0 where Type_Id=1--⽗节点union allselect b.Type_Id,b.ParentId,b.Type_Namefromtab a,--⽗节点数据集Sys_ParamType_V2_0 b--⼦节点数据集where b.ParentId=a.Type_Id --⼦节点数据集.ID=⽗节点数据集.parendID)select * from tab;--查找从⼦节点到定级节点的路径with tab as(select Type_Id,ParentId,Type_Name,cast(Type_Id as varchar(100)) as fulltypeidfrom SKU_ProductType where Type_Id=423--⼦节点union allselectb.Type_Id,b.ParentId,b.Type_Name,cast(a.fulltypeid+','+cast(b.Type_Id as nvarchar(100)) as varchar(100)) as fulltypeidfromtab a,--⼦节点数据集SKU_ProductType b --⽗节点数据集where a.ParentId=b.Type_Id --⼦节点数据集.parendID=⽗节点数据集.ID)select * from tab ;--------------结果--------------423410蜂花粉423410347蜂产品423,4103475营养⾷品423,410,34750健康保健423,410,347,5实际WITH tree AS(SELECT ID,PID,0as level,cast(ID as varchar(1000)) fullid,CAST(AREA_NAME as varchar(1000)) fullnameFROM YUN_BASE_AREAWHERE PID='0'UNION ALLSELECT child.ID,child.PID,parent.level+1,cast(fullid+','+child.ID as varchar(1000)) fullid,cast(fullname+'>'+child.AREA_NAME as varchar(1000)) fullidFROM YUN_BASE_AREA as childinner join tree parenton parent.ID=child.PID)SELECT * FROM tree order by fullnameselect * from YUN_BASE_AREA where AREA_NAME='亚洲'结果。
sql递归 +level 查询语法
sql递归+level 查询语法在SQL中,递归查询通常涉及使用WITH RECURSIVE语句来创建递归公共表表达式(CTE)。
这允许你在查询中定义递归结构,并使用LEVEL或其他标识符来表示递归的深度。
下面是一个基本的递归查询语法示例:WITH RECURSIVE RecursiveCTE (column1, column2, ..., level) AS ( -- Anchor memberSELECT column1, column2, ..., 1 as levelFROM your_tableWHERE <your_condition>UNION ALL-- Recursive memberSELECT t.column1, t.column2, ..., r.level + 1FROM your_table tJOIN RecursiveCTE r ON <join_condition>WHERE <additional_conditions>)SELECT * FROM RecursiveCTE;在上面的示例中:•RecursiveCTE是递归公共表表达式的名称。
•column1, column2, ...是你要选择的列。
• 1 as level是递归的起始级别。
•<your_table>是你要查询的表。
•<your_condition>是用于选择起始行的条件。
•<join_condition>是用于连接递归成员与前一成员的条件。
•<additional_conditions>是可选的其他条件。
这个查询将从起始行开始,递归地连接符合条件的行,直到不再有符合条件的行为止。
level列用于跟踪递归的深度。
请注意,递归查询可能导致性能问题,因此在使用时要小心。
在某些数据库系统中,可能需要启用递归查询的特定选项。
CTE递归查询全解
CTE递归查询全解TSQL脚本能实现递归查询,⽤户使⽤共⽤表表达式 CTE(Common Table Expression),只需要编写少量的代码,就能实现递归查询。
本⽂详细介绍CTE递归调⽤的特性和使⽤⽰例,递归查询主要⽤于层次结构的查询,从叶级(Leaf Level)向顶层(Root Level)查询,或从顶层向叶级查询,或递归的路径(Path)。
⼀,递归查询原理递归调⽤是指⾃⼰调⽤⾃⼰,使⽤CTE实现递归查询必须满⾜三个条件:初始条件,递归调⽤表达式,终⽌条件,CTE 递归查询的伪代码如下:WITH cte_name ( column_name [,...n] )AS(--Anchor member is definedCTE_query_definitionUNION ALL--Recursive member is defined referencing cte_nameCTE_query_definition)-- Statement using the CTESELECT*FROM cte_name1,递归查询⾄少包含两个⼦查询:第⼀个⼦查询称作定点(Anchor)⼦查询:定点查询只是⼀个返回有效表的查询,⽤于设置递归的初始值;第⼆个⼦查询称作递归⼦查询:该⼦查询调⽤CTE名称,触发递归查询,实际上是递归⼦查询调⽤递归⼦查询;两个⼦查询使⽤union all,求并集;2,CTE的递归终⽌条件递归查询没有显式的递归终⽌条件,只有当递归⼦查询返回空结果集(没有数据⾏返回)或是超出了递归次数的最⼤限制时,才停⽌递归。
默认的递归查询次数是100,可以使⽤查询提⽰(hint):MAXRECURSION 控制递归的最⼤次数:OPTION( MAXRECURSION 16);如果允许⽆限制的递归次数,使⽤查询提⽰:option(maxrecursion 0);当递归查询达到指定或默认的 MAXRECURSION 数量限制时,SQL Server将结束查询并返回错误,如下:The statement terminated. The maximum recursion 10 has been exhausted before statement completion.事务执⾏失败,该事务包含的所有操作都被回滚。
sql语句 递归
sql语句递归SQL语句中的递归是指在查询过程中,通过引用同一表的不同行来实现对数据的迭代处理。
递归查询在某些场景下非常有用,比如树形结构、层级关系等数据的查询和处理。
本文将介绍10个不同的使用递归的SQL语句示例。
1. 查找某个员工的所有下属员工```sqlWITH RECURSIVE subordinates AS (SELECT employee_id, employee_nameFROM employeesWHERE manager_id = :employee_idUNION ALLSELECT e.employee_id, e.employee_nameFROM employees eJOIN subordinates s ON e.manager_id = s.employee_id)SELECT * FROM subordinates;```这个SQL语句使用递归查询,从employees表中查询出某个员工的所有下属员工,包括直接下属和间接下属。
2. 计算某个员工的所有下属员工数量```sqlWITH RECURSIVE subordinates AS (SELECT employee_id, employee_nameFROM employeesWHERE manager_id = :employee_idUNION ALLSELECT e.employee_id, e.employee_nameFROM employees eJOIN subordinates s ON e.manager_id = s.employee_id)SELECT COUNT(*) FROM subordinates;```这个SQL语句在上一个示例的基础上,通过COUNT函数计算出某个员工的所有下属员工数量。
3. 查找某个部门及其所有的下属部门```sqlWITH RECURSIVE subdepartments AS (SELECT department_id, department_nameFROM departmentsWHERE parent_department_id = :department_idUNION ALLSELECT d.department_id, d.department_nameFROM departments dJOIN subdepartments s ON d.parent_department_id = s.department_id)SELECT * FROM subdepartments;```这个SQL语句使用递归查询,从departments表中查询出某个部门及其所有的下属部门,包括直接下属和间接下属。
sql中的递归
sql中的递归递归是一种在计算机科学中广泛使用的编程技术,它允许我们定义一个函数或过程,该函数或过程可以调用自身来解决问题。
在SQL中,我们可以使用递归来解决一些复杂的问题,如层次查询和树形结构的处理。
## 1. 什么是递归?递归是指在一个过程中,函数或者子程序通过调用自身的方式来解决问题的方法。
每次调用自身时,都会将问题规模缩小,直到达到基本情况,然后逐步返回结果。
## 2. SQL中的递归查询在SQL中,我们可以使用`WITH RECURSIVE`语句来创建递归查询。
这个语句首先定义了一个临时的结果集(称为公共表表达式),然后在这个结果集上进行递归操作。
递归查询的基本语法如下:```sqlWITH RECURSIVE recursive_table_name (column1, column2, ...)AS (-- 非递归部分:初始值SELECT ...FROM ...UNION ALL-- 递归部分:递归条件SELECT ...FROM ...JOIN recursive_table_name ON ...)SELECT ...FROM recursive_table_name;```- `recursive_table_name`是递归表的名称。
- `column1, column2, ...`是递归表中的列名。
- `UNION ALL`用于连接非递归部分和递归部分。
- 在递归部分,我们需要引用`recursive_table_name`来实现递归。
## 3. 示例:层级查询假设我们有一个员工表,每个员工有一个上级领导,我们想要获取所有的员工及其上级领导的信息。
这是一个典型的层次查询问题,可以使用递归来解决。
```sqlCREATE TABLE Employee (id INT PRIMARY KEY,name VARCHAR(50),manager_id INT,FOREIGN KEY (manager_id) REFERENCES Employee(id));INSERT INTO Employee VALUES (1, '张三', NULL);INSERT INTO Employee VALUES (2, '李四', 1);INSERT INTO Employee VALUES (3, '王五', 2);INSERT INTO Employee VALUES (4, '赵六', 2);INSERT INTO Employee VALUES (5, '孙七', 3);```现在,我们想要获取所有的员工及其上级领导的信息。
sql语句 递归
sql语句递归递归在SQL语句中主要用于解决树状结构的查询问题,可以通过递归查询获取树状结构的所有节点或者某个节点的所有子节点。
下面列举了10个使用递归的SQL语句示例。
1. 查询某个节点的所有子节点```sqlWITH RECURSIVE cte AS (SELECT id, name, parent_idFROM nodesWHERE id = :node_idUNION ALLSELECT n.id, , n.parent_idFROM nodes nINNER JOIN cte ON n.parent_id = cte.id)SELECT *FROM cte;```2. 查询某个节点的所有父节点```sqlWITH RECURSIVE cte AS (SELECT id, name, parent_idFROM nodesWHERE id = :node_idUNION ALLSELECT n.id, , n.parent_idFROM nodes nINNER JOIN cte ON n.id = cte.parent_id )SELECT *FROM cte;```3. 查询某个节点的所有祖先节点```sqlWITH RECURSIVE cte AS (SELECT id, name, parent_idFROM nodesWHERE id = :node_idUNION ALLSELECT n.id, , n.parent_idFROM nodes nINNER JOIN cte ON n.id = cte.parent_id)SELECT *FROM cteWHERE id <> :node_id;```4. 查询某个节点的所有子孙节点的数量```sqlWITH RECURSIVE cte AS (SELECT id, parent_idFROM nodesWHERE id = :node_idUNION ALLSELECT n.id, n.parent_idFROM nodes nINNER JOIN cte ON n.parent_id = cte.id )SELECT COUNT(*) AS descendant_count FROM cte;```5. 查询某个节点的所有子孙节点的深度```sqlWITH RECURSIVE cte AS (SELECT id, parent_id, 1 AS depthFROM nodesWHERE id = :node_idUNION ALLSELECT n.id, n.parent_id, cte.depth + 1FROM nodes nINNER JOIN cte ON n.parent_id = cte.id)SELECT MAX(depth) AS max_depthFROM cte;```6. 查询某个节点的所有子孙节点的路径```sqlWITH RECURSIVE cte AS (SELECT id, name, parent_id, CAST(name AS VARCHAR(1000)) AS pathFROM nodesWHERE id = :node_idUNION ALLSELECT n.id, , n.parent_id, CONCAT(cte.path, ' > ',)FROM nodes nINNER JOIN cte ON n.parent_id = cte.id)SELECT *FROM cte;```7. 查询某个节点的所有子节点的数量及其父节点名称```sqlWITH RECURSIVE cte AS (SELECT id, name, parent_idFROM nodesWHERE id = :node_idUNION ALLSELECT n.id, , n.parent_idFROM nodes nINNER JOIN cte ON n.parent_id = cte.id)SELECT COUNT(*) AS child_count, AS parent_name FROM cteGROUP BY ;```8. 查询某个节点的所有父节点的数量及其子节点名称```sqlWITH RECURSIVE cte AS (SELECT id, name, parent_idFROM nodesWHERE id = :node_idUNION ALLSELECT n.id, , n.parent_idFROM nodes nINNER JOIN cte ON n.id = cte.parent_id)SELECT COUNT(*) AS parent_count, AS child_name FROM cteGROUP BY ;```9. 查询某个节点的所有子节点的数量及其路径```sqlWITH RECURSIVE cte AS (SELECT id, name, parent_id, CAST(name AS VARCHAR(1000)) AS pathFROM nodesWHERE id = :node_idUNION ALLSELECT n.id, , n.parent_id, CONCAT(cte.path, ' > ', )FROM nodes nINNER JOIN cte ON n.parent_id = cte.id)SELECT COUNT(*) AS child_count, pathFROM cteGROUP BY path;```10. 查询某个节点的所有父节点的数量及其路径```sqlWITH RECURSIVE cte AS (SELECT id, name, parent_id, CAST(name AS VARCHAR(1000)) AS pathFROM nodesWHERE id = :node_idUNION ALLSELECT n.id, , n.parent_id, CONCAT(, ' > ',cte.path)FROM nodes nINNER JOIN cte ON n.id = cte.parent_id)SELECT COUNT(*) AS parent_count, pathFROM cteGROUP BY path;```这些示例展示了递归在SQL语句中的应用,通过递归可以实现对树状结构的灵活查询和分析。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
收稿日期:2007201208作者简介:刘 进(1981-),男,辽宁沈阳人,江西服装职业技术学院教师,华东交通大学信息工程学院在职研究生・第25卷 第2期2007年4月沈阳师范大学学报(自然科学版)Journal of S henyang Norm al U niversity (N atural Science )V ol 125,N o.2Apr.2007文章编号:1673-5862(2007)02-0217-03浅谈T 2SQL 语言之递归查询刘 进(江西服装职业技术学院计算机系,江西南昌 330201)摘 要:文章以T 2SQL 技术为基础,介绍了基于CTE 语句进行数据库查询的产生机理和实现方法,并针对CTE 语句的特点,采用存储过程及自定义函数方式来实现基于CTE 语句查询数据库的过程・以人员管理树型结构数据为基础,在SQL Server 2005中建立各种CTE 临时结果集,进行递归查询操作,从而体现T 2SQL 语言中新增CTE 递归查询的强大功能・关 键 词:T 2SQL ;CTE ;存储过程中图分类号:TP 311.132.3 文献标识码:A1 CTE (Common Table Expression )综述在现实生活中,树型结构数据屡见不鲜:组织机构、产品结构、人事关系等等・经常在项目中涉及到对机构、人员数据进行处理,特别是进行统计、聚集等操作的时候,一直没有一个好的处理方法・临时表、视图、程序控制等方法都用使用过了,但在处理效率上达不到理想目标・归根结底,就是在数据库中,对数据的操作方式(不管是SQL 语言,SP ,V IEW …)不像程序语言那样灵活、高效率・过去使用SQLServer 2000处理上述问题要不增加查询嵌套层数不使用游标,但编写繁杂度都比较大至于程序执行效率也不理想・在2005年12月微软推出了SQL Server 2005,在其T 2SQL 语句中的CTE 功能使得上面的问题迎刃而解・CTE (Common Table Expression )是SQL Server 2005众多新特性之一,它是一个可以由定义语句引用的临时命名结果集・总括描述CTE 就像是视图,只不过使用起来更加简单(不用再Create View ,Drop View 之类)・本质上,CTE 是一个临时结果集,仅仅存在于它发生的语句中・又可以在SEL ECT ,INSER T ,DEL ETE 、U PDA TE 或CTEA TE V IEW 语句中建立一个CTE ,最重要的特点是实现递归查询・CTE 类似于派生表,其优点是与派生表不同,CTE 能够引用自己本身・如果在查询时不想存储视图,可以用一个CTE 来代替它,在一个语句中还可以多次引用CTE ・其实CTE 递归查询和原子与分子查询有很多相似之处・原子查询建立一个表,而分子查询建立在原子查询之上,提供清晰与重复利用・应用CTE 也可以达到同样的目的・使用时可以将查询区域分割成可读的“块”,然后用这些块建立一个复杂的查询・CTE 通过关键字WITH 建立,其模板为:WITH CTE -name[(column -name [,…n ])]AS(CTE -query -specification )如果在CTE 定义中提到的栏名称是唯一的,那么可以不必命名,也可以对它们重新命名・2 数据实例假设某个部门的人员管理层次如图1所示,在这个例子中,一个人可以领导零至多个人,但每个人只被一个人领导或没有领导・具体关系是赵一最大,管理所有下属,没有人管理赵一・钱一被赵一管理,图1 人员管理数据示意图但同时他又管理着孙一和孙二・孙二和钱二同钱一情况雷同・但像钱三就只有领导没有下属,相同情况的还有孙一,孙三,孙四,李一,李二・首先在Microsoft SQL Server ManagementStudio 中建立表:人员管理・代码如下・代码一:create table 人员管理(编号int primary key identity (1,1),姓名varchar (10)not null ,领导编号int )在这张人员管理表中有3个属性,编号是主码唯一标识一个元组;姓名是每个人的姓名,领导编号是该人领导人的编号・接着在这张表中加入图1中的每个元组(人)・如代码二所示・代码二:insert into 人员管理values (‘赵一’,0)insert into 人员管理values (‘钱一’,1)insert into 人员管理values (‘钱二’,1)insert into 人员管理values (‘钱三’,1)insert into 人员管理values (‘孙一’,2)insert into 人员管理values (‘孙二’,2)insert into 人员管理values (‘孙三’,3)insert into 人员管理values (‘孙四’,3)insert into 人员管理values (‘李一’,6)insert into 人员管理values (‘李二’,6)一般在讨论递归函数时,大概得强调3个部分:初始的调用,重复地调用自己,结束当前递归过程的返回测试・递归的CTE 也可类比这3部分,不变成员是初始调用,递归成员是重复调用自己,而测试返回数据集合,一般是SEL ECT 语句・以代码三为例稍作递归CET 说明・代码三是实现显示下属员工的一个存储过程,通过输入两个参数(员工编号和他管理的下属层次)便可以显示他的下属员工・首选建立一个存储过程,然后建立CTE 递归查询语句,CTE 名称为rollup ,有4个属性,第四属性深度是后加上去的,用来显示下属员工所在的层次・在代码三中3至5行属递归中不变成员的初始调用即显示编号为@ID 的员工;第7和第8行作用是递归成员重复调用部分;这两部分用union all 语句连接;第三步用SEL ECT 语句把结果返回;最后调用此存储过程・代码三:create proc rygl1(@ID int ,@sd int )aswith rollup (编号,姓名,领导编号,深度)as (select 编号,姓名,领导编号,0as 深度from 人员管理where 编号=@IDunion allselect 人员管理・编号,人员管理・姓名,人员管理・领导编号,深度+1as 深度from 人员管理join rollup on rollup ・编号=人员管理・领导编号and 深度〈@sd 21)select 3from rollupgoexec rygl11,3具体运行结果如图2所示・利用代码三rygl1存储过程来找出1号员工和其三层下属・可以看到员工赵一在根部,因为他的深度为0,还可看到员工钱一、钱二和钱三直接是赵一的下属,其余的员工都是赵一的间接下属并有一个相应的深度・在这个例中查找的是1号(赵一)包括自身在内的三层下属,所以812沈阳师范大学学报(自然科学版) 第25卷图2 代码三运行结果没有李一和李二・除了能够回滚一个实体及它的子孙外,该函数还可用来找出一个实体的所有祖先,这也可以用一个递归查询来完成・代码四rygl2是代码三rygl1互相补充的存储过程,它通过简单的逆转,使用父—子关系来实现・注意第八行的变化・代码四:create proc rygl2(@ID int )aswith rollup (编号,姓名,领导编号,关系)as (select 编号,姓名,领导编号,convert (nvarchar (max ),‘.’+姓名+‘.’)as 关系from 人员管理where 编号=@IDunion allselect 人员管理・编号,人员管理・姓名,人员管理・领导编号,convert (nvarchar (max ),关系+人员管理.姓名+‘.’)as 关系from 人员管理join rollup on rollup ・领导编号=人员管理・编号)select max (关系)as 祖先关系from rollup go图3 代码四运行结果exec rygl210由于在递归创建数据时,不变成员和递归成员的数据结构要完全一样,包括数据类型,长度与精确位数・因此在程序代码四中要先将定义路径的字段转换成相同的nvarchar (max )数据类型・上述代码招执行结构如图3・3 结 语CTE 的真正威力在于它们的递归功能,即CTE 可以包含对它们自身的引用・递的CTE 是根据至少两个查询(或者用递归查询的说法称为成员)构建的・一个是非递归查询,也称为锚定成员(AM )・另一个是递归查询,也称为递归成员(RM )・两个查询由UN ION ALL 运算符连接为一个单独的CTE ・SQL Server 2005中的T 2SQL 语言有了非常大的改进,CTE 就是一个典型的事例功能,它解决了T 2SQL 语言的递归查询问题・CTE 是SQL Server 2005的一项强大而灵活的功能,使得SQL Server 的可读性更强,更易于管理,降低了查询的复杂程度・直至现在,关系数据库在技术日新月异的IT 界依然雄霸市场,T 2SQL 又是SQL Server 核心技术,未来T 2SQL 的强大功能,会更令人期待与惊叹・参考文献:[1]胡江奕・基于SQL Server 的数据库应用系统性能的优化[J ].计算机工程与应用,2001,37(2):95297.[2]常 伟.SQL 中查询语句的优化方法[J ].重庆工学院学报,2006,20(5):91293.[3]胡百敬.SQL Server 2005数据库开发详解[M ].北京:电子工业出版社,2007:1402149.[4]BEAUCHEMIN B ,SULL IVAN D.SQL Server 2005开发者指南[M ].北京:清华大学出版社,2007:2432249.[5]GUNDERLO Y M.SQL Server 2005从入门到精通[M ].北京:电子工业出版社,2006:1202129.On R ecurrence Q uery of the Language T 2SQ LL IU Ji n(Department of Computer ,Jiangxi College of G arment Industry ,Nanchang 330201,China )Abstract :This Article is based on T 2SQL technique.It introduces mechanism and method of using CTE to search a Database.According to the characteristics of CTE ,this paper adopts storage processing and definition function to realize the process of searching Database through CTE.With tree data structure of personnel management ,it also builds up various temporary result gathers of CTE in SQL Server 2005to complete the recurrence search operation ,so that it shows strong function of recurrence query of CTE in the language of T 2SQL.K ey w ords :T 2SQL ;CTE ;storage processing 912第2期 刘 进:浅谈T 2SQL 语言之递归查询。