资讯

精准传达 • 有效沟通

从品牌网站建设到网络营销策划,从策略到执行的一站式服务

oracle如何实现递归,oracle递归向上汇总

ORACLE select 递归查询

START WITH 定义数据行查询的初始起点;

成都创新互联专注骨干网络服务器租用十余年,服务更有保障!服务器租用,西部信息服务器托管 成都服务器租用,成都服务器托管,骨干网络带宽,享受低延迟,高速访问。灵活、实现低成本的共享或公网数据中心高速带宽的专属高性能服务器。

CONNECT BY prior 定义表中的各个行是如何联系的;

connect by 后面的"prior" 如果缺省,则只能查询到符合条件的起始行,并不进行递归查询;

条件2:col_1 = col_2,col_1是父键(它标识父),col_2是子键(它标识子)。

条件3过滤递归前相应节点及其子节点,如果上级节点不满足则下级节点自动过滤掉;

条件4过滤递归后相应的节点或子节点,如果上级节点不满足则下级结点自动提升一级。

系统伪列:

CURRVAL AND NEXTVAL 使用序列号的保留字

ROWID 记录的唯一标识

ROWNUM 限制查询结果集的数量

LEVEL 显示层次树中特定行的层次或级别

CONNECT_BY_ROOT 返回当前层的根节点(当前行数据所对应的最高等级节点的内容)

SYS_CONNECT_BY_PATH(column, char) 函数实现将从父节点到当前行内容以"path"或者层次元素列表的形式显示出来

CONNECT_BY_ISCYCLE 须带参数NOCYCLE,当前行中引用了某个父亲节点的内容并在树中出现了循环,如果循环显示"1",否则就显示"0"。

CONNECT_BY_ISLEAF 判断当前行是不是叶子。如果是叶子显示"1",如果不是叶子而是一个分支(例如当前内容是其他行的父亲)就显示"0"

而在 Oracle 10g 中,只要指定"NOCYCLE"就可以进行任意的查询操作。与这个关键字相关的还有一个伪列——CONNECT_BY_ISCYCLE, 如果在当前行中引用了某个父亲节点的内容并在树中出现了循环,那么该行的伪列中就会显示"1",否则就显示"0"。

【实例】

--创建测试表,增加测试数据

create table test(superid varchar2(20),id varchar2(20),mc varchar2(20));

insert into test values('0','1','A1');

insert into test values('0','2','A2');

insert into test values('1','11','A11');

insert into test values('1','12','A12');

insert into test values('2','21','A21');

insert into test values('2','22','A22');

insert into test values('11','111','A111');

insert into test values('11','112','A112');

insert into test values('12','121','A121');

insert into test values('12','122','A122');

insert into test values('21','211','A211');

insert into test values('21','212','A212');

insert into test values('22','221','A221');

insert into test values('22','222','A222');

commit;

--层次查询示例

select level||'级' jc,lpad(' ',(level-1)*4)||id id,mc

from test

start with superid = '0' connect by prior id=superid;

select level||'级' jc,connect_by_isleaf mxf,lpad(' ',(level-1)*4)||id id,mc

from test

start with superid = '0' connect by prior id=superid;

--给出两个以前在"数据库字符串分组相加之四"中的例子来理解start with ... connect by ...

--功能:实现按照superid分组,把id用";"连接起来

--实现:以下两个例子都是通过构造2个伪列来实现connect by连接的。

ORACLE递归

about connect by

SELECT empno, ename, job, mgr, deptno, LEVEL, sys_connect_by_path(ename,'\'), connect_by_root(ename) FROM emp START WITH mgr IS NULL CONNECT BY mgr =  PRIOR empno

WITH T(empno, ename, job, mgr, deptno, the_level, path,top_manager) AS ( ---- 必须把结构写出来

SELECT empno, ename, job, mgr, deptno  ---- 先写锚点查询,用START WITH的条件

,1 AS the_level    ---- 递归起点,第一层

,'\'||ename        ---- 路径的第一截

,ename AS top_manager ---- 原来的CONNECT_BY_ROOT

FROM scott.EMP

WHERE mgr IS NULL ---- 原来的START WITH条件

UNION ALL  ---- 下面是递归部分

SELECT e.empno, e.ename, e.job, e.mgr, e.deptno  ---- 要加入的新一层数据,来自要遍历的emp表

,1 + t.the_level            ---- 递归层次,在原来的基础上加1。这相当于CONNECT BY查询中的LEVEL伪列

,t.path||'\'||e.ename        ---- 把新的一截路径拼上去

,t.top_manager              ---- 直接继承原来的数据,因为每个路径的根节点只有一个

FROM t, scott.emp e                    ---- 典型写法,把子查询本身和要遍历的表作一个连接

WHERE t.empno = e.mgr            ---- 原来的CONNECT BY条件

) ---- WITH定义结束

SELECT * FROM T

EMPNO ENAME      JOB        MGR DEPTNO  THE_LEVEL PATH                                                                            TOP_MANAGER

----- ---------- --------- ----- ------ ---------- -------------------------------------------------------------------------------- -----------

7839 KING      PRESIDENT          10          1 \KING                                                                            KING

7566 JONES      MANAGER    7839    20          2 \KING\JONES                                                                      KING

7698 BLAKE      MANAGER    7839    30          2 \KING\BLAKE                                                                      KING

7782 CLARK      MANAGER    7839    10          2 \KING\CLARK                                                                      KING

7999 MIKE      ANALYST    7566    30          3 \KING\JONES\MIKE                                                                KING

7499 ALLEN      SALESMAN  7698    30          3 \KING\BLAKE\ALLEN                                                                KING

7521 WARD      SALESMAN  7698    30          3 \KING\BLAKE\WARD                                                                KING

7654 MARTIN    SALESMAN  7698    30          3 \KING\BLAKE\MARTIN                                                              KING

7788 SCOTT      ANALYST    7566    20          3 \KING\JONES\SCOTT                                                                KING

7844 TURNER    SALESMAN  7698    30          3 \KING\BLAKE\TURNER                                                              KING

7900 JAMES      CLERK      7698    30          3 \KING\BLAKE\JAMES                                                                KING

7902 FORD      ANALYST    7566    20          3 \KING\JONES\FORD                                                                KING

7934 MILLER    CLERK      7782    10          3 \KING\CLARK\MILLER                                                              KING

7369 SMITH      CLERK      7902    20          4 \KING\JONES\FORD\SMITH                                                          KING

7876 ADAMS      CLERK      7788    20          4 \KING\JONES\SCOTT\ADAMS                                                          KING

oracle 中怎样递归查询出子节点的最上层父节点,并且其父节点是自身

1、创建测试表,create table test_connect(id number, p_id number);

2、插入测试数据,

insert into test_connect values(1,1);

insert into test_connect values(2,1);

insert into test_connect values(3,2);

insert into test_connect values(4,3);

commit;

3、查询数据表内容,select * from test_connect ,

4、执行递归查询语句,加入nocycle要素,不会出现【ORA-01436: 用户数据中的 CONNECT BY 循环的错误】,执行结果如下,

select *

from test_connect t

start with id = 4

connect by nocycle prior t.p_id = t.id

oracle 存储过程 递归实现 依赖分析

下面是用oracle数据库解决不用start with 来查询子父数据查询方法,里面主要用到了substr 和instr 函数(这两个函数,其他数据库也有相对应的函数),游标(其他数据库也有游标)。

-- 1 前提:创建表以及插入数据

CREATE TABLE TMP_TEST(MAIN_COLUMN VARCHAR2(10),PARENT_COLUMN VARCHAR2(10));

INSERT INTO TMP_TEST(MAIN_COLUMN,PARENT_COLUMN) VALUES('A',NULL);

INSERT INTO TMP_TEST(MAIN_COLUMN,PARENT_COLUMN) VALUES('B','A');

INSERT INTO TMP_TEST(MAIN_COLUMN,PARENT_COLUMN) VALUES('C','A');

INSERT INTO TMP_TEST(MAIN_COLUMN,PARENT_COLUMN) VALUES('D','A');

INSERT INTO TMP_TEST(MAIN_COLUMN,PARENT_COLUMN) VALUES('E','B');

INSERT INTO TMP_TEST(MAIN_COLUMN,PARENT_COLUMN) VALUES('F','C');

INSERT INTO TMP_TEST(MAIN_COLUMN,PARENT_COLUMN) VALUES('G','E');

-- 2 创建存储过程

CREATE OR REPLACE PROCEDURE GET_TREE(IS_PARENT   IN NUMBER /** 子父查询 **/,

SEARCH_ID   IN VARCHAR2 /** 查询条件节点 **/,

TREE_RESOUT OUT VARCHAR2 /** 输出结果集合 **/)

AS

V_TEMP VARCHAR2(4000);

V_SEARCH VARCHAR2(4000);

V_INDEX INTEGER;

BEGIN

V_TEMP :=SEARCH_ID||'-';

TREE_RESOUT := '';

WHILE length(V_TEMP) 0 LOOP

V_INDEX := instr(V_TEMP,'-');

V_SEARCH := substr(V_TEMP,0,V_INDEX-1);

V_TEMP := substr(V_TEMP,V_INDEX+1);

/*DBMS_OUTPUT.put_line('V_INDEX:'|| V_INDEX ||'V_TEMP:' ||V_TEMP||'V_SEARCH:'|| V_SEARCH);*/

/** 查询子节点 **/

if(IS_PARENT = 1) THEN

FOR C1 IN (SELECT * FROM TMP_TEST T1 WHERE T1.PARENT_COLUMN = V_SEARCH) LOOP

TREE_RESOUT := TREE_RESOUT || C1.MAIN_COLUMN;

V_TEMP := V_TEMP || C1.MAIN_COLUMN || '-';

END LOOP;

ELSE

/** 查询父节点 **/

FOR C1 IN (SELECT * FROM TMP_TEST T1 WHERE T1.MAIN_COLUMN = V_SEARCH) LOOP

TREE_RESOUT := TREE_RESOUT || C1.PARENT_COLUMN;

V_TEMP := V_TEMP || C1.PARENT_COLUMN || '-';

END LOOP;

END IF;

END LOOP;

/*DBMS_OUTPUT.put_line('TREE_RESOUT:'||TREE_RESOUT);*/

END;

-- 3 调用存储过程

declare

TREE_RESULT VARCHAR2(4000);

SEARCH_ID VARCHAR2(4000);

begin

get_tree(1,'A',TREE_RESULT);

dbms_output.put_line('查询子节点:' || TREE_RESULT);

get_tree(0,'G',TREE_RESULT);

dbms_output.put_line('查询父节点:' || TREE_RESULT);

end;

Oracle递归查询:使用prior实现树操作

select * from tableName

start with  条件A   -- 开始递归的根节点,可多个条件

connect  by prior  条件B  -- prior  决定查询的索引顺序

where 条件 C

select t.empno,t.mgr,t.deptno ,level

from emp t

connect by prior t.empno=t.mgr

order by level,t.mgr,t.deptno;

找到empno为7369的所有领导。

select t.*,t.rowid from emp t

start with t.empno = 7369       --从empno为7369的开始查找

connect by prior t.mgr = t.empno ;    --上一条数据(这里就是empno为7369)的mgr == 当前遍历这一条数据的empno(那么就会找到empno为7902的用户)

找到empno为7566的所有下属

select t.*,t.rowid from emp t

start with t.empno = 7566

connect by prior t.empno = t.mgr ; --注意:connect by  t.mgr =prior t.empno与左边写法含义一样

start with :设置起点,省略后默认以全部行为起点。

connect by [condition] :与一般的条件一样作用于当前列,但是在满足条件后,会以全部列作为下一层级递归(没有其他条件的话)。

prior : 表示上一层级的标识符。经常用来对下一层级的数据进行限制。不可以接伪列。

level :伪列,表示当前深度。

connect_by_root() :显示根节点列。经常用来分组。

connect_by_isleaf :1是叶子节点,0不是叶子节点。在制作树状表格时必用关键字。

sys_connect_by_path() :将递归过程中的列进行拼接。

nocycle , connect_by_iscycle : 在有循环结构的查询中使用。

siblings : 保留树状结构,对兄弟节点进行排序

;request_id=162538763316780265474850biz_id=0utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v29-22-52652111.first_rank_v2_pc_rank_v29_1utm_term=ORACLE%E9%80%92%E5%BD%92%E5%87%BD%E6%95%B0spm=1018.2226.3001.4187

;request_id=162538763316780269872688biz_id=0utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-5-108683534.first_rank_v2_pc_rank_v29_1utm_term=ORACLE%E9%80%92%E5%BD%92%E5%87%BD%E6%95%B0spm=1018.2226.3001.4187

;request_id=162538763316780265474850biz_id=0utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v29-10-105773226.first_rank_v2_pc_rank_v29_1utm_term=ORACLE%E9%80%92%E5%BD%92%E5%87%BD%E6%95%B0spm=1018.2226.3001.4187


当前文章:oracle如何实现递归,oracle递归向上汇总
链接分享:http://cdkjz.cn/article/dsdpjoh.html
多年建站经验

多一份参考,总有益处

联系快上网,免费获得专属《策划方案》及报价

咨询相关问题或预约面谈,可以通过以下方式与我们联系

大客户专线   成都:13518219792   座机:028-86922220