- 浏览: 955415 次
- 性别:
- 来自: 魔都
文章分类
- 全部博客 (745)
- MultiThread (19)
- My Plan (118)
- JavaBasic (61)
- MyInterview (104)
- InternetTechnique (5)
- ProjectConclusion (1)
- Maven (5)
- MogoDb (5)
- Hadoop (11)
- Memcached (6)
- TechniqueCollect (1)
- Ibaits (1)
- Android (34)
- ItLife (40)
- Tree (2)
- ProjectArchitect (7)
- Open Source (3)
- liunx (5)
- socket (8)
- Spring (27)
- DesginPattern (35)
- WebBasic (13)
- English (13)
- structs (1)
- structs2 (2)
- Oracle (17)
- Hibernate (2)
- JavaScript (4)
- Jdbc (1)
- Jvm (15)
- Ibatis (1)
- DataStructures (13)
- Https/Socket/Tcp/Ip (3)
- Linux (4)
- Webservice (7)
- Io (2)
- Svn (1)
- Css (1)
- Ajax (1)
- ExtJs (1)
- UML (2)
- DataBase (6)
- BankTechnique (3)
- SpringMvc (3)
- Nio (3)
- Load Balancing/Cluster (3)
- Tools (1)
- javaPerformanceOptimization (8)
- Lucene(SEO) (1)
- My Think (80)
- NodeJs (1)
- Quartz (1)
- Distributed-java (1)
- MySql (7)
- Project (4)
- junit (4)
- framework (1)
- enCache (1)
- git (2)
- SCJP (1)
- sd (1)
最新评论
-
lkjxshi:
你都这水平了还考这个证干嘛
SCJP 认证考试指南 -
钟逸华:
问的真多
百度java开发面试题(转) -
zuimeitulip:
觉得我就是这样的,从小阅读量就很少,导致现在的读的速度非常慢, ...
让读书成为一种习惯 -
DDT_123456:
我觉得你是不符合要求。问你hashmap的那个问题,你那样回答 ...
阿里面试2(转) -
jingjing0907:
刚刚写了很多读过此博客的感受,竟然没有发上去,以为我注册账号还 ...
让读书成为一种习惯
收集的几条在oracle中通过connect by prior来实现递归查询
Start with...Connect By子句递归查询一般用于一个表维护树形结构的应用。
创建示例表:
CREATE TABLE TBL_TEST
(
ID NUMBER,
NAME VARCHAR2(100 BYTE),
PID NUMBER DEFAULT 0
);
插入测试数据:
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('1','10','0');
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('2','11','1');
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('3','20','0');
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('4','12','1');
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('5','121','2');
从Root往树末梢递归
select * from TBL_TEST
start with id=1
connect by prior id = pid
从末梢往树ROOT递归
select * from TBL_TEST
start with id=5
connect by prior pid = id
==============================================
有一张表 t
字段:
parent
child
两个字段的关系是父子关系
写一个sql语句,查询出指定父下面的所有的子
比如
a b
a c
a e
b b1
b b2
c c1
e e1
e e3
d d1
指定parent=a,选出
a b
a c
a e
b b1
b b2
c c1
e e1
e e3
SQL语句:
select parent,child from test start with parent='a'
connect by prior child=parent
[1] [2] [3] [4] 下一页
connect by 是结构化查询中用到的,其基本语法是:
select ... from tablename start by cond1
connect by cond2
where cond3;
简单说来是将一个树状结构存储在一张表里,比如一个表中存在两个字段:
id,parentid那么通过表示每一条记录的parent是谁,就可以形成一个树状结构。
用上述语法的查询可以取得这棵树的所有记录。
其中COND1是根结点的限定语句,当然可以放宽限定条件,以取得多个根结点,实际就是多棵树。
COND2是连接条件,其中用PRIOR表示上一条记录,比如 CONNECT BY PRIOR ID=PRAENTID就是说上一条记录的ID是本条记录的PRAENTID,即本记录的父亲是上一条记录。
COND3是过滤条件,用于对返回的所有记录进行过滤。
PRIOR和START WITH关键字是可选项
PRIORY运算符必须放置在连接关系的两列中某一个的前面。对于节点间的父子关系,PRIOR
运算符在一侧表示父节点,在另一侧表示子节点,从而确定查找树结构是的顺序是自顶向下还是
自底向上。在连接关系中,除了可以使用列名外,还允许使用列表达式。START WITH 子句为
可选项,用来标识哪个节点作为查找树型结构的根节点。若该子句被省略,则表示所有满足查询
条件的行作为根节点。
完整的例子如SELECT PID,ID,NAME FROM T_WF_ENG_WFKIND START WITH PID =0 CONNECT BY PRIOR ID = PID
以上主要是针对上层对下层的顺向递归查询而使用start with ... connect by prior ...这种方式,但有时在需求需要的时候,可能会需要由下层向上层的逆向递归查询,此是语句就有所变化:例如要实现 select * from table where id in ('0','01','0101','0203','0304') ;现在想把0304的上一级03给递归出来,0203的上一级02给递归出来,而01现在已经是存在的,最高层为0.而这张table不仅仅这些数据,但我现在只需要('0','01','0101','0203','0304','02','03')这些数据,此时语句可以这样写SELECT PID,ID,NAME FROM V_WF_WFKIND_TREE WHERE ID IN (SELECT DISTINCT(ID) ID FROM V_WF_WFKIND_TREE CONNECT BY PRIOR PID = ID START WITH ID IN ('0','01','0101','0203','0304') );
其中START WITH ID IN里面的值也可以替换SELECT 子查询语句.
注意由上层向下层递归与下层向上层递归的区别在于START WITH...CONNECT BY PRIOR...的先后顺序以及 ID = PID 和 PID = ID 的微小变化!
=============================================================
connect by prior start with 经常会被用到一个表中存在递归关系的时候。比如我们经常会将一个比较复杂的目录树存储到一个表中。或者将一些部门存储到一个表中,而这些部门互相有隶属关系。这个时候你就会用到connect by prior start with。
典型的使用方法就是:
select * from table connect by prior cur_id=parent_id start with cur_id=???
例如:
a b
1 0
2 1
3 1
4 2
5 3
如果想查找a=2及其下面的所有数据,则:
select * from table connect by prior a=b start with a=2
a b
2 1
4 2
这些只是基础,皮毛。其实只要你灵活的构造查询语句。可以得出意想不到的结果。比如生成树每一个路径。
但是这些记录组成的树必须正常才可以。如果有互为父子的情况,就会出现循环错误!
select * from tb_cus_area_cde
--子取父
select * from tb_cus_area_cde a
CONNECT BY PRIOR a.c_snr_area=a.c_area_cde START WITH a.c_area_cde='1040101'
--父取子
select * from tb_cus_area_cde a
CONNECT BY PRIOR a.c_area_cde=a.c_snr_area START WITH a.c_snr_area is null
注意:在用这个函数的时候,statement的参数要用 ResultSet.TYPE_SCROLL_INSENSITIVE 而不能用 ResultSet.TYPE_SCROLL_SENSITIVE,在这里再把这两个之间的区别讲讲:
1.TYPE_FORWORD_ONLY,只可向前滚动;
2.TYPE_SCROLL_INSENSITIVE,双向滚动,但不及时更新,就是如果数据库里的数据修改过,并不在ResultSet中反应出来。
3.TYPE_SCROLL_SENSITIVE,双向滚动,并及时跟踪数据库的更新,以便更改ResultSet中的数据
10g树形查询特性CONNECT_BY_ISCYCLE
在10g中Oracle提供了新的伪列:CONNECT_BY_ISCYCLE,通过这个伪列,可以判断是否在树形查询的过程中构成了循环,这个伪列只是在CONNECT BY NOCYCLE方式下有效。
这一篇描述一下解决问题的思路。
CONNECT_BY_ISCYCLE的实现和前面两篇文章中CONNECT_BY_ROOT和CONNECT_BY_ISLEAF的实现完全不同。
因为要实现CONNECT_BY_ISCYCLE,就必须先实现CONNECT BY NOCYCLE,而在9i中是没有方法实现这个功能的。
也就是说,首先要实现自己的树形查询的功能,而仅这第一点,就是一个异常困难的问题,何况后面还要实现NOCYCLE,最后再加上一个ISCYCLE的判断。
所以总的来说,这个功能的实现比前面两个功能要复杂得多。由于树形查询的LEVEL是不固定的,所以采用链接的方式实现,基本上是不现实的。换句话说,用纯SQL的方式来实现树形查询的功能基本上不可行。而为了解决这个功能,只能通过PL/SQL配合SQL来实现。
仍然是首先构造一个例子:
SQL> CREATE TABLE T_TREE (ID NUMBER, FATHER_ID NUMBER, NAME VARCHAR2(30));
表已创建。
SQL> INSERT INTO T_TREE VALUES (1, 0, 'A');
已创建 1 行。
SQL> INSERT INTO T_TREE VALUES (2, 1, 'BC');
已创建 1 行。
SQL> INSERT INTO T_TREE VALUES (3, 1, 'DE');
已创建 1 行。
SQL> INSERT INTO T_TREE VALUES (4, 1, 'FG');
已创建 1 行。
SQL> INSERT INTO T_TREE VALUES (5, 2, 'HIJ');
已创建 1 行。
SQL> INSERT INTO T_TREE VALUES (6, 4, 'KLM');
已创建 1 行。
SQL> INSERT INTO T_TREE VALUES (7, 6, 'NOPQ');
已创建 1 行。
SQL> INSERT INTO T_TREE VALUES (0, 0, 'ROOT');
已创建 1 行。
SQL> INSERT INTO T_TREE VALUES (4, 7, 'FG');
已创建 1 行。
SQL> COMMIT;
提交完成。
SQL> SELECT * FROM T_TREE;
ID FATHER_ID NAME
---------- ---------- ------------------------------
1 0 A
2 1 BC
3 1 DE
4 1 FG
5 2 HIJ
6 4 KLM
7 6 NOPQ
0 0 ROOT
4 7 FG
已选择9行。
上面构造了两种树形查询循环的情况,一种是当前记录的自循环,另一种是树形查询的某个子节点是当前节点的祖先节点,从而构成了循环。在这个例子中,记录ID为0和ID为4且FATHER_ID等于7的两条记录分别构成了上述的两种循环的情况。
下面就来看看CONNECT_BY_ISCYCLE和CONNECT BY NOCYCLE的功能:
SQL> SELECT *
2 FROM T_TREE
3 START WITH ID = 0
4 CONNECT BY PRIOR ID = FATHER_ID;
ERROR:
ORA-01436: 用户数据中的 CONNECT BY 循环
未选定行
SQL> SELECT *
2 FROM T_TREE
3 START WITH ID = 1
4 CONNECT BY PRIOR ID = FATHER_ID;
ERROR:
ORA-01436: 用户数据中的 CONNECT BY 循环
未选定行
这就是不使用CONNECT BY NOCYCLE的情况,查询会报错,指出树形查询中出现循环,在10g中可以使用CONNECT BY NOCYCLE的方式来避免错误的产生:
SQL> SELECT *
2 FROM T_TREE
3 START WITH ID = 0
4 CONNECT BY NOCYCLE PRIOR ID = FATHER_ID;
ID FATHER_ID NAME
---------- ---------- ------------------------------
0 0 ROOT
1 0 A
2 1 BC
5 2 HIJ
3 1 DE
4 1 FG
6 4 KLM
7 6 NOPQ
已选择8行。
上一页 [1] [2] [3] [4] 下一页
使用CONNECT BY NOCYCLE,Oracle自动避免循环的产生,将不产生循环的数据查询出来,下面看看CONNECT_BY_ISCYCLE的功能:
SQL> SELECT ID,
2 FATHER_ID,
3 NAME,
4 CONNECT_BY_ISCYCLE CYCLED
5 FROM T_TREE
6 START WITH ID = 0
7 CONNECT BY NOCYCLE PRIOR ID = FATHER_ID;
ID FATHER_ID NAME CYCLED
---------- ---------- ------------------------------ ----------
0 0 ROOT 1
1 0 A 0
2 1 BC 0
5 2 HIJ 0
3 1 DE 0
4 1 FG 0
6 4 KLM 0
7 6 NOPQ 1
已选择8行。
可以看到,CONNECT_BY_ISCYCLE伪列指出循环在树形查询中发生的位置。
为了实现CONNECT_BY_ISCYCLE就必须先实现CONNECT BY NOCYCLE方式,而这在9i中是没有现成的办法的,所以这里尝试使用PL/SQL来自己实现树形查询的功能。
SQL> CREATE OR REPLACE FUNCTION F_FIND_CHILD(P_VALUE VARCHAR2) RETURN VARCHAR2 AS
2 V_STR VARCHAR2(32767) := '/' || P_VALUE;
3
4 PROCEDURE P_GET_CHILD_STR (P_FATHER IN VARCHAR2, P_STR IN OUT VARCHAR2) AS
5 BEGIN
6 FOR I IN (SELECT ID FROM T_TREE WHERE FATHER_ID = P_FATHER AND FATHER_ID != ID) LOOP
7 IF INSTR(P_STR || '/', '/' || I.ID || '/') = 0 THEN
8 P_STR := P_STR || '/' || I.ID;
9 P_GET_CHILD_STR(I.ID, P_STR);
10 END IF;
11 END LOOP;
12 END;
13 BEGIN
14 P_GET_CHILD_STR(P_VALUE, V_STR);
15 RETURN V_STR;
16 END;
17 /
函数已创建。
构造一个函数,在函数中递归调用过程来实现树形查询的功能。
下面看看调用这个函数的结果:
SQL> SELECT F_FIND_CHILD(0) FROM DUAL;
F_FIND_CHILD(0)
------------------------------------------------
/0/1/2/5/3/4/6/7
SQL> SELECT F_FIND_CHILD(2) FROM DUAL;
F_FIND_CHILD(2)
------------------------------------------------
/2/5
SQL> SELECT F_FIND_CHILD(4) FROM DUAL;
F_FIND_CHILD(4)
------------------------------------------------
/4/6/7
虽然目前存在的问题还有很多,但是已经基本上实现了一个最简单的NOCYCLE的SYS_CONNECT_BY_PATH的功能。
Start with...Connect By子句递归查询一般用于一个表维护树形结构的应用。
创建示例表:
CREATE TABLE TBL_TEST
(
ID NUMBER,
NAME VARCHAR2(100 BYTE),
PID NUMBER DEFAULT 0
);
插入测试数据:
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('1','10','0');
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('2','11','1');
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('3','20','0');
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('4','12','1');
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('5','121','2');
从Root往树末梢递归
select * from TBL_TEST
start with id=1
connect by prior id = pid
从末梢往树ROOT递归
select * from TBL_TEST
start with id=5
connect by prior pid = id
==============================================
有一张表 t
字段:
parent
child
两个字段的关系是父子关系
写一个sql语句,查询出指定父下面的所有的子
比如
a b
a c
a e
b b1
b b2
c c1
e e1
e e3
d d1
指定parent=a,选出
a b
a c
a e
b b1
b b2
c c1
e e1
e e3
SQL语句:
select parent,child from test start with parent='a'
connect by prior child=parent
[1] [2] [3] [4] 下一页
connect by 是结构化查询中用到的,其基本语法是:
select ... from tablename start by cond1
connect by cond2
where cond3;
简单说来是将一个树状结构存储在一张表里,比如一个表中存在两个字段:
id,parentid那么通过表示每一条记录的parent是谁,就可以形成一个树状结构。
用上述语法的查询可以取得这棵树的所有记录。
其中COND1是根结点的限定语句,当然可以放宽限定条件,以取得多个根结点,实际就是多棵树。
COND2是连接条件,其中用PRIOR表示上一条记录,比如 CONNECT BY PRIOR ID=PRAENTID就是说上一条记录的ID是本条记录的PRAENTID,即本记录的父亲是上一条记录。
COND3是过滤条件,用于对返回的所有记录进行过滤。
PRIOR和START WITH关键字是可选项
PRIORY运算符必须放置在连接关系的两列中某一个的前面。对于节点间的父子关系,PRIOR
运算符在一侧表示父节点,在另一侧表示子节点,从而确定查找树结构是的顺序是自顶向下还是
自底向上。在连接关系中,除了可以使用列名外,还允许使用列表达式。START WITH 子句为
可选项,用来标识哪个节点作为查找树型结构的根节点。若该子句被省略,则表示所有满足查询
条件的行作为根节点。
完整的例子如SELECT PID,ID,NAME FROM T_WF_ENG_WFKIND START WITH PID =0 CONNECT BY PRIOR ID = PID
以上主要是针对上层对下层的顺向递归查询而使用start with ... connect by prior ...这种方式,但有时在需求需要的时候,可能会需要由下层向上层的逆向递归查询,此是语句就有所变化:例如要实现 select * from table where id in ('0','01','0101','0203','0304') ;现在想把0304的上一级03给递归出来,0203的上一级02给递归出来,而01现在已经是存在的,最高层为0.而这张table不仅仅这些数据,但我现在只需要('0','01','0101','0203','0304','02','03')这些数据,此时语句可以这样写SELECT PID,ID,NAME FROM V_WF_WFKIND_TREE WHERE ID IN (SELECT DISTINCT(ID) ID FROM V_WF_WFKIND_TREE CONNECT BY PRIOR PID = ID START WITH ID IN ('0','01','0101','0203','0304') );
其中START WITH ID IN里面的值也可以替换SELECT 子查询语句.
注意由上层向下层递归与下层向上层递归的区别在于START WITH...CONNECT BY PRIOR...的先后顺序以及 ID = PID 和 PID = ID 的微小变化!
=============================================================
connect by prior start with 经常会被用到一个表中存在递归关系的时候。比如我们经常会将一个比较复杂的目录树存储到一个表中。或者将一些部门存储到一个表中,而这些部门互相有隶属关系。这个时候你就会用到connect by prior start with。
典型的使用方法就是:
select * from table connect by prior cur_id=parent_id start with cur_id=???
例如:
a b
1 0
2 1
3 1
4 2
5 3
如果想查找a=2及其下面的所有数据,则:
select * from table connect by prior a=b start with a=2
a b
2 1
4 2
这些只是基础,皮毛。其实只要你灵活的构造查询语句。可以得出意想不到的结果。比如生成树每一个路径。
但是这些记录组成的树必须正常才可以。如果有互为父子的情况,就会出现循环错误!
select * from tb_cus_area_cde
--子取父
select * from tb_cus_area_cde a
CONNECT BY PRIOR a.c_snr_area=a.c_area_cde START WITH a.c_area_cde='1040101'
--父取子
select * from tb_cus_area_cde a
CONNECT BY PRIOR a.c_area_cde=a.c_snr_area START WITH a.c_snr_area is null
注意:在用这个函数的时候,statement的参数要用 ResultSet.TYPE_SCROLL_INSENSITIVE 而不能用 ResultSet.TYPE_SCROLL_SENSITIVE,在这里再把这两个之间的区别讲讲:
1.TYPE_FORWORD_ONLY,只可向前滚动;
2.TYPE_SCROLL_INSENSITIVE,双向滚动,但不及时更新,就是如果数据库里的数据修改过,并不在ResultSet中反应出来。
3.TYPE_SCROLL_SENSITIVE,双向滚动,并及时跟踪数据库的更新,以便更改ResultSet中的数据
10g树形查询特性CONNECT_BY_ISCYCLE
在10g中Oracle提供了新的伪列:CONNECT_BY_ISCYCLE,通过这个伪列,可以判断是否在树形查询的过程中构成了循环,这个伪列只是在CONNECT BY NOCYCLE方式下有效。
这一篇描述一下解决问题的思路。
CONNECT_BY_ISCYCLE的实现和前面两篇文章中CONNECT_BY_ROOT和CONNECT_BY_ISLEAF的实现完全不同。
因为要实现CONNECT_BY_ISCYCLE,就必须先实现CONNECT BY NOCYCLE,而在9i中是没有方法实现这个功能的。
也就是说,首先要实现自己的树形查询的功能,而仅这第一点,就是一个异常困难的问题,何况后面还要实现NOCYCLE,最后再加上一个ISCYCLE的判断。
所以总的来说,这个功能的实现比前面两个功能要复杂得多。由于树形查询的LEVEL是不固定的,所以采用链接的方式实现,基本上是不现实的。换句话说,用纯SQL的方式来实现树形查询的功能基本上不可行。而为了解决这个功能,只能通过PL/SQL配合SQL来实现。
仍然是首先构造一个例子:
SQL> CREATE TABLE T_TREE (ID NUMBER, FATHER_ID NUMBER, NAME VARCHAR2(30));
表已创建。
SQL> INSERT INTO T_TREE VALUES (1, 0, 'A');
已创建 1 行。
SQL> INSERT INTO T_TREE VALUES (2, 1, 'BC');
已创建 1 行。
SQL> INSERT INTO T_TREE VALUES (3, 1, 'DE');
已创建 1 行。
SQL> INSERT INTO T_TREE VALUES (4, 1, 'FG');
已创建 1 行。
SQL> INSERT INTO T_TREE VALUES (5, 2, 'HIJ');
已创建 1 行。
SQL> INSERT INTO T_TREE VALUES (6, 4, 'KLM');
已创建 1 行。
SQL> INSERT INTO T_TREE VALUES (7, 6, 'NOPQ');
已创建 1 行。
SQL> INSERT INTO T_TREE VALUES (0, 0, 'ROOT');
已创建 1 行。
SQL> INSERT INTO T_TREE VALUES (4, 7, 'FG');
已创建 1 行。
SQL> COMMIT;
提交完成。
SQL> SELECT * FROM T_TREE;
ID FATHER_ID NAME
---------- ---------- ------------------------------
1 0 A
2 1 BC
3 1 DE
4 1 FG
5 2 HIJ
6 4 KLM
7 6 NOPQ
0 0 ROOT
4 7 FG
已选择9行。
上面构造了两种树形查询循环的情况,一种是当前记录的自循环,另一种是树形查询的某个子节点是当前节点的祖先节点,从而构成了循环。在这个例子中,记录ID为0和ID为4且FATHER_ID等于7的两条记录分别构成了上述的两种循环的情况。
下面就来看看CONNECT_BY_ISCYCLE和CONNECT BY NOCYCLE的功能:
SQL> SELECT *
2 FROM T_TREE
3 START WITH ID = 0
4 CONNECT BY PRIOR ID = FATHER_ID;
ERROR:
ORA-01436: 用户数据中的 CONNECT BY 循环
未选定行
SQL> SELECT *
2 FROM T_TREE
3 START WITH ID = 1
4 CONNECT BY PRIOR ID = FATHER_ID;
ERROR:
ORA-01436: 用户数据中的 CONNECT BY 循环
未选定行
这就是不使用CONNECT BY NOCYCLE的情况,查询会报错,指出树形查询中出现循环,在10g中可以使用CONNECT BY NOCYCLE的方式来避免错误的产生:
SQL> SELECT *
2 FROM T_TREE
3 START WITH ID = 0
4 CONNECT BY NOCYCLE PRIOR ID = FATHER_ID;
ID FATHER_ID NAME
---------- ---------- ------------------------------
0 0 ROOT
1 0 A
2 1 BC
5 2 HIJ
3 1 DE
4 1 FG
6 4 KLM
7 6 NOPQ
已选择8行。
上一页 [1] [2] [3] [4] 下一页
使用CONNECT BY NOCYCLE,Oracle自动避免循环的产生,将不产生循环的数据查询出来,下面看看CONNECT_BY_ISCYCLE的功能:
SQL> SELECT ID,
2 FATHER_ID,
3 NAME,
4 CONNECT_BY_ISCYCLE CYCLED
5 FROM T_TREE
6 START WITH ID = 0
7 CONNECT BY NOCYCLE PRIOR ID = FATHER_ID;
ID FATHER_ID NAME CYCLED
---------- ---------- ------------------------------ ----------
0 0 ROOT 1
1 0 A 0
2 1 BC 0
5 2 HIJ 0
3 1 DE 0
4 1 FG 0
6 4 KLM 0
7 6 NOPQ 1
已选择8行。
可以看到,CONNECT_BY_ISCYCLE伪列指出循环在树形查询中发生的位置。
为了实现CONNECT_BY_ISCYCLE就必须先实现CONNECT BY NOCYCLE方式,而这在9i中是没有现成的办法的,所以这里尝试使用PL/SQL来自己实现树形查询的功能。
SQL> CREATE OR REPLACE FUNCTION F_FIND_CHILD(P_VALUE VARCHAR2) RETURN VARCHAR2 AS
2 V_STR VARCHAR2(32767) := '/' || P_VALUE;
3
4 PROCEDURE P_GET_CHILD_STR (P_FATHER IN VARCHAR2, P_STR IN OUT VARCHAR2) AS
5 BEGIN
6 FOR I IN (SELECT ID FROM T_TREE WHERE FATHER_ID = P_FATHER AND FATHER_ID != ID) LOOP
7 IF INSTR(P_STR || '/', '/' || I.ID || '/') = 0 THEN
8 P_STR := P_STR || '/' || I.ID;
9 P_GET_CHILD_STR(I.ID, P_STR);
10 END IF;
11 END LOOP;
12 END;
13 BEGIN
14 P_GET_CHILD_STR(P_VALUE, V_STR);
15 RETURN V_STR;
16 END;
17 /
函数已创建。
构造一个函数,在函数中递归调用过程来实现树形查询的功能。
下面看看调用这个函数的结果:
SQL> SELECT F_FIND_CHILD(0) FROM DUAL;
F_FIND_CHILD(0)
------------------------------------------------
/0/1/2/5/3/4/6/7
SQL> SELECT F_FIND_CHILD(2) FROM DUAL;
F_FIND_CHILD(2)
------------------------------------------------
/2/5
SQL> SELECT F_FIND_CHILD(4) FROM DUAL;
F_FIND_CHILD(4)
------------------------------------------------
/4/6/7
虽然目前存在的问题还有很多,但是已经基本上实现了一个最简单的NOCYCLE的SYS_CONNECT_BY_PATH的功能。
发表评论
-
十步完全理解SQL(转)
2014-01-12 22:27 776本文由 伯乐在线 - 水果泡腾片 翻译自 Lukas Ede ... -
Oracle数据库优化的几点总结(转)
2013-11-10 19:01 945个人理解,数据库性能 ... -
ORACLE-SQL性能优化
2013-07-31 23:11 865ORACLE-SQL性能优化 博客分类: or ... -
SQL语句的解析过程
2013-05-15 21:49 980由于最近需要做一些sql query性能提升的研究, ... -
数据库优化(sql优化)
2012-07-11 21:33 1175数据库优化(sql优化) 1.sql优化: 1.选择最有效的 ... -
(转)浅谈数据库设计技巧(下)
2012-04-24 00:19 1347三、多用户及其权限 ... -
sql优化34条
2012-04-24 00:15 725我们要做到不但会写SQL,还要做到写出性能优良的SQL,以下为 ... -
(转)浅谈数据库设计技巧(上)
2012-04-24 00:13 877(转)浅谈数据库设计 ... -
什么是SQL注入式攻击
2012-04-18 19:54 1103什么是SQL注入式攻击? 所谓SQL注入式攻击,就是攻击者把 ... -
大数据量高并发的数据库优化与sql优化
2012-04-15 14:46 12000大数据量高并发的数据库优化 一、数据库结构的设计 ... -
oracle的导出与导入
2012-04-08 01:01 1058C:\Documents and Settings\Admin ... -
Oracle开发人员应该具备的几个资源-入门基础
2012-03-10 00:49 1384很多开发者,舍近求远,愿意花大价钱到书店买Oracle的大头 ... -
oracle中 connect by prior 递归算法 -- 理解
2012-03-08 23:10 1054oracle中 connect by prior 递 ... -
大数据量,海量数据 处理方法总结
2012-03-07 00:39 1226大数据量,海量数据 处理方法总结 最近有点忙,稍微空闲下 ... -
海量数据处理
2012-03-07 00:37 881海量数据 ... -
Oracle 游标使用大全
2012-03-04 15:54 896[转] Oracle 游标使用大全 我们将讨论各种用于访问 ...
相关推荐
### Oracle Start With.Connect By Prior 子句实现递归查询 #### 概述 在Oracle数据库中,`Start With.Connect By Prior`子句是执行递归查询的一种强大工具,主要用于处理层次结构数据。这类数据通常存在于组织...
### Oracle中的Connect By Prior递归算法详解 #### 一、Connect By Prior 子句概述 在Oracle数据库中,`Connect By Prior`子句是一种非常有用的工具,尤其在处理具有层次结构的数据时。它允许用户以一种简洁的方式...
在Oracle数据库中,递归查询可以通过`START WITH CONNECT BY PRIOR`语句实现。此语句允许用户按照树状结构来检索数据。 ##### 1. `START WITH CONNECT BY PRIOR`用法详解 **基本语法**: ```sql SELECT * FROM ...
递归树形结构查询主要依赖于`CONNECT BY`和`PRIOR`关键字,它们允许我们构建复杂的层级查询,以展示数据的层次关系。 在Oracle中,树形结构查询的基本语法如下: ```sql SELECT [LEVEL], * FROM table_name START ...
Oracle 查询树型关系是指使用 START WITH 和 CONNECT BY 子句来实现 SQL 的层次查询。从 Oracle 9i 开始,可以通过 SYS_CONNECT_BY_PATH 函数实现将父节点到当前行内容以“path”或者层次元素列表的形式显示出来。 ...
本文将详细介绍如何在Oracle中使用递归查询,并通过具体的示例来展示其用法。 #### 二、递归查询的基础概念 递归查询是Oracle中一种特殊的查询方式,主要用于检索具有层次结构的数据。在Oracle中实现递归查询需要...
Oracle数据库中的`CONNECT BY PRIOR`是一个强大的查询构造器,用于处理树形数据结构,尤其在组织层级、部门结构或者员工管理系统中非常常见。这个功能允许我们从一个或多个根节点开始,按照指定的规则遍历整个树结构...
在`Oracle中的树状查询(递归查询) - 鱼与飞鸟 - CSDNBlog.htm`这篇博客中,作者通过具体的实例详细讲解了如何在权限查询中使用递归查询,包括如何建立树形结构,以及如何避免无限递归等问题。 8. **补充资源** - ...
这里,我们将深入探讨如何使用递归查询来构建菜单树,并特别关注在MySQL和Oracle这两种广泛使用的数据库系统中的实现。 首先,我们要理解什么是递归查询。递归查询是一种在数据库中处理层次数据的方法,它通过自身...
ORACLE通过CONNECT BY子句来实现递归查询。CONNECT BY子句通常配合START WITH子句使用,其中START WITH指定了递归的起点,而CONNECT BY用于定义父子关系。CONNECT BY子句中的PRIOR关键字用于表示层级之间的连接,它...
本文将通过一个具体的例子来详细介绍如何在 Oracle 中实现递归查询。 #### 二、基础知识回顾 在深入讨论之前,我们需要先了解几个基础概念: 1. **START WITH 子句**:用于指定递归查询的起始条件。 2. **CONNECT ...
在Oracle数据库中,递归查询主要依赖于`START WITH`和`CONNECT BY PRIOR`两个关键语法。本文将详细介绍这些概念以及具体的使用方法。 #### 二、创建示例表 为了更好地理解Oracle中的递归查询,我们首先需要创建...
connect by递归查询基本语法是: select 1 from 表格 start with … connect by prior id = pId start with:表示以什么为根节点,不加限制可以写1=1,要以id为123的节点为根节点,就写为start with id =123 ...
DB2虽然没有直接提供类似Oracle的`CONNECT_BY`功能,但可以通过自连接和临时表的方式来实现递归查询。一个典型的例子是使用`WITH RECURSIVE`子句: ```sql WITH RECURSIVE employee_tree (level, employee_id, ...
本文将深入探讨如何通过递归查询来解决这类问题,并着重讲解使用`WITH`语句来实现递归查询的方法,适用于多种数据库系统,如MySQL、PostgreSQL、SQL Server等。 一、理解递归查询 递归查询是一种在数据库中遍历层级...
在本主题中,我们将深入探讨如何利用递归SQL在Oracle中展示一棵树形结构,以及如何根据父ID遍历所有的子ID。 首先,让我们分析给出的SQL查询语句: 1. `start with id = #id#` 这是递归查询的起点,`#id#`是一个...
通过以上详细的解析和示例,我们可以看出`START WITH` 和 `CONNECT BY PRIOR` 这两个特性在Oracle数据库中处理层级结构数据的强大能力。它们不仅能够帮助我们构建出树形结构的结果集,还能有效地进行复杂的数据筛选...
oracle菜单树查询 使用实例 使用START WITH CONNECT BY PRIOR子句实现递归查询
总结来说,`START WITH...CONNECT BY PRIOR`子句是Oracle SQL处理树形数据的关键工具,通过它可以有效地查询和展示层次关系的数据。理解并熟练运用这个子句,能够帮助你在处理具有层级结构的业务场景时更加游刃有余...