使用oracle 9i 里的层级查询(Hierarchical Queries)实现树状表结构的递归数据查询

来源:互联网 发布:xmind 8 pro 破解 mac 编辑:程序博客网 时间:2024/05/19 17:27

先来看2张图:

这个图展示了ORACLE查询一个层级树时的返回顺序,从Root节点开始返回该Root的一个子节点,
然后再返回该子节点的子节点,一直到叶结点.
在下一个有子节点的节点被找到并且该节点不是叶结idan以前,层级会逐渐增加,并且Oracle返回该节点
当Root节点的第一个节点的所有的"子孙(descendants)"节点被返回后,Oracle才会去查找下一个子节点,这个过程将一直持续.(深度优先)
(This process continues, with Oracle returning to the root row for the next child
only when all of the "descendants" of the first child row have been returned.)


这个图说明了 Hierarchical Queries 的语法
1.以指定的层级根不开始
2.由指定的层级中父子关系连接,在一个层级查询中,条件表达式必须使用PRIOR运算符限定查取父级数据.
比喻:
... PRIOR expr = expr
or
... expr = PRIOR expr
如果CONNECT BY是符合条件,那么只有一个条件限定PRIOR运算符.(例子将在下面给出)
先建表,插入一些数据:

Create Table TreeDemo (
    NodeID  NVARCHAR2(
50Default '' Not Null,
    Parent_NodeID  NVARCHAR2(
50Default '' Not Null,
    NodeName  NVARCHAR2(
100Default '' Not Null
Constraint PK_TreeDemo Primary Key (NodeID)
);
insert into TreeDemo values('A',0,'A_1');
insert into TreeDemo values('A01','A','A_01');
insert into TreeDemo values('A02','A','A_02');
insert into TreeDemo values('A03','A01','A_03');
insert into TreeDemo values('A04','A01','A_02');

用这LPAD和SYS_CONNECT_BY_PATH函数把树型结构构造出来
LPAD 函数将左边的字符串填充特定的字符空格
SYS_CONNECT_BY_PATH ORACLE树结构专用函数

SELECT LPAD(' '2*level-1)||SYS_CONNECT_BY_PATH(NodeName, '/') "TREE"
FROM TreeDemo
start 
with NodeID = 'A04' 
connect 
by prior NodeID = Parent_NodeID ;

结果为:

TREE
---------------------
 /A_02
   
/A_02/A_01
     
/A_02/A_01/A_1

在使用 start with ....connect by prio 查询前需要注意一点:
如果 prio 后面的关系弄反了查出来的结果是不一样的.
看看下面2条查询语句的结果:

1.这种查询将把当前符合条件的节点作为根节点遍历查询其所属子节点:

select * from TreeDemo
start 
with NodeID = 'A01' 
connect 
by prior NodeID = Parent_NodeID ;
NODEID    PARENT_NODEID   NODENAME
--------- -------------  --------- 
A01      A          A_01
A03       A01          A_03
A04      A01          A_03    

2.这种查询将由叶结点遍历查询到根节点:

start with NodeID = 'A04' 
connect 
by prior Parent_NodeID = NodeID ;
NODEID    PARENT_NODEID   NODENAME
--------- -------------  --------- 
A04      A01          A_02
A01       A          A_01
A         
0          A_1

3.带条件过滤:

select * from TreeDemo
start 
with NodeID = 'A04' 
connect 
by PARENT_NODEID <>'0' and prior Parent_NodeID = NodeID ;
NODEID    PARENT_NODEID   NODENAME
--------- -------------  --------- 
A04      A01          A_02
A01       A          A_01

也可在查询里加上排序条件,可以看出在ORACLE里处理这种树型数据表是很方便的,在MS SQL 里可能要写函数处理.