SQL递归查询(SqlServer/ORACLE递归查询)[语法差异分析]

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介: 在 SQLSERVER2005以后,mssql开始有了递归查询的方法了。比较起最开始写存储过程或者写function的方式。这样的方式更加简便灵活的。而oracle也有自带的树形结构递归查询方法,connect by下面我自己写的一段SQL,简单注释下CTE共用表达式的一些用法。

在 SQLSERVER2005以后,mssql开始有了递归查询的方法了。比较起最开始写存储过程或者写function的方式。这样的方式更加简便灵活的。

而oracle也有自带的树形结构递归查询方法,connect by

下面我自己写的一段SQL,简单注释下CTE共用表达式的一些用法。 实现对树状结构的根节点和子节点的查询。

复制代码
代码
-- ----------------------------------------------------------------------
--
author:jc_liumangtu(【DBA】小七)
--
date:    2010-03-30 15:09:42
--
version:
--
Microsoft SQL Server 2005 - 9.00.1399.06 (Intel X86)
--
     Oct 14 2005 00:33:37
--
     Copyright (c) 1988-2005 Microsoft Corporation
--
     Developer Edition on Windows NT 5.1 (Build 2600: Service Pack 3)
--

--
----------------------------------------------------------------------
use test
set nocount on
if object_id ( ' Dept ' , ' U ' ) is not null
drop table Dept
go
create table Dept(ID int ,ParentID int ,Name varchar ( 20 ))  
insert into Dept select 1 , 0 , ' AA '
insert into Dept select 2 , 1 , ' BB '
insert into Dept select 3 , 1 , ' CC '  
insert into Dept select 4 , 2 , ' DD '  
insert into Dept select 5 , 3 , ' EE '  
insert into Dept select 6 , 0 , ' FF '
insert into Dept select 7 , 6 , ' GG '
insert into Dept select 8 , 7 , ' HH '
insert into Dept select 9 , 7 , ' II '
insert into Dept select 10 , 7 , ' JJ '
insert into Dept select 11 , 9 , ' KK '

go   
SELECT * FROM Dept;

-- 查询树状结构某节点的上级所有根节点。
with cte_root(ID,ParentID,NAME)
as
(
   
-- 起始条件
    select ID,ParentID,NAME
   
from Dept
   
where Name = ' II '    -- 列出子节点查询条件
    union all
   
-- 递归条件
    select a.ID,a.ParentID,a.NAME
   
from Dept a
   
inner join
    cte_root b         
-- 执行递归,这里就要理解下了
    on a.ID = b.ParentID  -- 根据基础表条件查询子节点(a.ID),通过CTE递归找到其父节点(b.ParentID)。
)                       -- 可以和下面查询子节点的cte_child对比。
select * from cte_root ;

-- 查询树状结构某节点下的所有子节点。
with cte_child(ID,ParentID,NAME)
as
(
   
-- 起始条件
    select ID,ParentID,NAME
   
from Dept
   
where Name = ' II ' -- 列出父节点查询条件
    union all
   
-- 递归条件
    select a.ID,a.ParentID,a.NAME
   
from Dept a
   
inner join
    cte_child b
   
on ( a.ParentID = b.ID)  -- 根据查询到的父节点(a.Parent),通过CTE递归查询出其子节点(b.ID)
)

select * from cte_child -- 可以改变之前的查询条件'II'再测试结果


ID          ParentID    Name
-- --------- ----------- --------------------
1            0            AA
2            1            BB
3            1            CC
4            2            DD
5            3            EE
6            0            FF
7            6            GG
8            7            HH
9            7            II
10           7            JJ
11           9            KK

ID          ParentID    NAME
-- --------- ----------- --------------------
9            7            II
7            6            GG
6            0            FF

ID          ParentID    NAME
-- --------- ----------- --------------------
9            7            II
11           9            KK
复制代码

在msdn中介绍了CTE的一些限制:

至少有一个定位点成员和一个递归成员,当然,你可以定义多个定位点成员和递归成员,但所有定位点成员必须在递归成员的前面
定位点成员之间必须使用UNION ALL、UNION、INTERSECT、EXCEPT集合运算符,最后一个定位点成员与递归成员之间必须使用UNION ALL,递归成员之间也必须使用UNION ALL连接
定位点成员和递归成员中的字段数量和类型必须完全一致
递归成员的FROM子句只能引用一次CTE对象
递归成员中不允许出现下列项
    SELECT DISTINCT
    GROUP BY
    HAVING
    标量聚合
    TOP
    LEFT、RIGHT、OUTER JOIN(允许出现 INNER JOIN)
    子查询

接下来介绍下Oracle里面的递归查询方法,connect by prior ,start with。相对于SqlServer来说,Oracle的方法更加简洁明了,简单易懂。很容易就让人理解其用法。借来我会用和上面SqlServer同样的数据和结构进行代码演示,和对一些关键字的用法进行阐述。

SELECT …..

CONNECT BY {PRIOR 列名1=列名2|列名1=PRIOR 列名2}
[START WITH];

下面是代码测试:

复制代码
代码
-- 创建表
create table Dept(ID int ,ParentID int ,Name varchar ( 20 ));
-- 增加测试数据,和上面的SqlServer数据相同
insert into Dept  select 1 , 0 , ' AA ' from dual;
insert into Dept  select 2 , 1 , ' BB ' from dual;
insert into Dept  select 3 , 1 , ' CC '   from dual;
insert into Dept  select 4 , 2 , ' DD '   from dual;
insert into Dept  select 5 , 3 , ' EE '   from dual;
insert into Dept  select 6 , 0 , ' FF ' from dual;
insert into Dept  select 7 , 6 , ' GG ' from dual;
insert into Dept  select 8 , 7 , ' HH ' from dual;
insert into Dept  select 9 , 7 , ' II ' from dual;
insert into Dept  select 10 , 7 , ' JJ ' from dual;
insert into Dept  select 11 , 9 , ' KK ' from dual;
commit ;

-- 查询根节点(父节点)
select * from Dept            -- 查询基础表
connect by id = prior parentid  -- connect by就是字段的关联关键字,prior有预先和前的意思,则是放在哪个字段前,哪个就是递归的上一层
start with name = ' II ' ;         -- start with则是递归的起始位置,也可以用id或者是parentid。可以修改II的值测试其他数据。

-- 查询结果
ID    PARENTID    NAME
9       7             II
7       6             GG
6       0             FF

-- 查询子节点

select * from Dept
connect
by prior id = parentid  -- 同样的语句,仅仅改变prior位子,就发生了指向性的变化,就是这里id为递归上一层。
start with name = ' II ' ;

-- 查询结果
ID    PARENTID    NAME
9        7             II
11     9             KK

-- 测试结果和SqlServer一致,语句却更精练,简洁易懂。
复制代码

经过分别对SqlServer和Oracle的测试,发现两个数据库都很好的支持递归查询,相比之下Oracle的递归查询语句更加简练易懂,更容易让人理解。

在做测试的时候,SqlServer更方便的产生测试数据,上面的代码可以复制后重复执行,而Oracle复制执行一次可以,重复执行的话,在执行创建表的工作,就会报错了,原因很简单,Oracle要判断表存在然后删除后重建的工作用代码实现很麻烦。而SqlServer只需要if后drop表再create就搞定。所以两种数据库各有千秋。

相关实践学习
使用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
目录
相关文章
|
19天前
|
SQL 人工智能 算法
【SQL server】玩转SQL server数据库:第二章 关系数据库
【SQL server】玩转SQL server数据库:第二章 关系数据库
61 10
|
21天前
|
SQL
sql语句加正则 简化查询
sql语句加正则 简化查询
16 0
sql语句加正则 简化查询
|
2月前
|
SQL
sql server链接查询
sql server链接查询
18 1
|
2月前
|
SQL
sql server简单查询
sql server简单查询
14 1
|
29天前
|
SQL 关系型数据库 MySQL
mysql一条sql查询出多个统计结果
mysql一条sql查询出多个统计结果
15 0
|
19天前
|
SQL 算法 数据库
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
91 6
|
2月前
|
SQL
sql高级查询
sql高级查询
13 0
|
6天前
|
SQL Java 数据库连接
Java从入门到精通:2.3.2数据库编程——了解SQL语言,编写基本查询语句
Java从入门到精通:2.3.2数据库编程——了解SQL语言,编写基本查询语句
|
14天前
|
SQL 安全 网络安全
IDEA DataGrip连接sqlserver 提示驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接的解决方法
IDEA DataGrip连接sqlserver 提示驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接的解决方法
34 0
|
2月前
|
SQL 数据库 数据安全/隐私保护
Sql Server数据库Sa密码如何修改
Sql Server数据库Sa密码如何修改

推荐镜像

更多