为了更好的查询一个树状结构的表,在Oracle的PL/SQL中提供乐一个诱人的特性——CONNECT BY子句。它大大的方便了我们查找树状表:遍历一棵树、寻找某个分支……,但还是存在一些不足。在Oracle <chmetcnv unitname="g" sourcevalue="10" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">10G</chmetcnv>,就对这个特性做了增强。下面就举例说明一下:
CONNECT_BY_ROOT
一张表,有多颗子树(根节点为0),现在我想知道每个节点属于哪个子树。举例:铃音目录结构下有多个大分类:中外名曲、流行经典、浪漫舞曲……,每个大类下面又有多个子类,子类下面还可以细分。那现在想要知道每个子类分属哪个大类,或者要统计每个大类下面有多少个子类。
看下面的例子,DIRINDEX分别为1、2、3的就是大分类,其他编号的都是子类或孙子类:
select dirindex, fatherindex, RPAD(' ', 2*(LEVEL-1)) || dirname from t_tonedirlib
start with fatherindex = 0
connect by fatherindex = prior dirindex
DIRINDEX FATHERINDEX DIRNAME
--------------------- ------------------------------------
1 0 中文经典
52 1 kkkkkkk
70 52 222
58 52 sixx
59 52 seven
69 52 uiouoooo
55 52 four
7 1 流行风云
8 1 影视金曲
1111 8 aaa
1112 8 bbb
1113 8 ccc
9 1 古典音乐
81 1 小熊之家
104 81 龙珠
105 81 snoppy
101 81 叮当1
102 81 龙猫
103 81 叮当2
2 0 热门流行
31 2 有奖活动
32 2 相约香格里拉
50 2 新浪彩铃
3 0 老歌回放
333 3 老电影
335 3 怀旧金曲
26 rows selected
如何统计1、2、3三个大类下有哪些子类,有多少个子类?在9i及以前要做这样的统计十分麻烦。现在10G提供了一个新特性:CONNECT_BY_ROOT,他的作用就是使结果不是当前的节点ID,而满足查询条件下的根节点的ID。以上面为例,我们需要得到以上结果只需要执行以下语句就可以搞定了:
select CONNECT_BY_ROOT dirindex, fatherindex, RPAD(' ', 2*(LEVEL-1)) || dirname from t_tonedirlib
start with fatherindex = 0
connect by fatherindex = prior dirindex
CONNECT_BY_ROOTDIRINDEX FATHERINDEX RPAD('',2*(LEVEL-1))||DIRNAME
----------------------- ------------- -----------------------------
1 0 中文经典
1 1 kkkkkkk
1 52 222
1 52 sixx
1 52 seven
1 52 uiouoooo
1 52 four
1 1 流行风云
1 1 影视金曲
1 8 aaa
1 8 bbb
1 8 ccc
1 1 古典音乐
1 1 小熊之家
1 81 龙珠
1 81 snoppy
1 81 叮当1
1 81 龙猫
1 81 叮当2
2 0 热门流行
2 2 有奖活动
2 2 相约香格里拉
2 2 新浪彩铃
3 0 老歌回放
3 3 老电影
3 3 怀旧金曲
26 rows selected
查出来的结果中,CONNECT_BY_ROOTDIRINDEX就是各个子类(孙子类)所属的大类编号,如果需要统计,就只要执行以下语句马上可以统计出来了:
select rootindex, count('X') from
(select CONNECT_BY_ROOT dirindex as rootindex
from t_tonedirlib
start with fatherindex = 0
connect by fatherindex = prior dirindex) a
group by a.rootindex
ROOTINDEX COUNT('X')
--------- ----------
1 19
2 4
3 3
3 rows selected
CONNECT_BY_ISLEAF
经常有DBA因为要查找树状表中的叶子节点而苦恼。大部分DBA为了解决这个问题就给表增加了一个字段来描述这个节点是否为叶子节点。但这样做有很大的弊端:需要通代码逻辑来保证这个字段的正确性。
Oracle 10G中提供了一个新特性——CONNECT_BY_ISLEAF——来解决这个问题了。简单点说,这个属性结果表明当前节点在满足条件的查询结果中是否为叶子节点, 0不是,1是:
select CONNECT_BY_ISLEAF, dirindex, fatherindex, RPAD(' ', 2*(LEVEL-1)) || dirname
from t_tonedirlib
start with fatherindex = 0
connect by fatherindex = prior dirindex
CONNECT_BY_ISLEAF DIRINDEX FATHERINDEX RPAD(' ',2*(LEVEL-1))||dirname
----------------- ---------------- ---------------------------------
0 1 0 中文经典
0 52 1 kkkkkkk
1 70 52 222
1 58 52 sixx
1 59 52 seven
1 69 52 uiouoooo
1 55 52 four
1 7 1 流行风云
0 8 1 影视金曲
1 1111 8 aaa
1 1112 8 bbb
1 1113 8 ccc
1 9 1 古典音乐
0 81 1 小熊之家
1 104 81 龙珠
1 105 81 snoppy
1 101 81 叮当1
1 102 81 龙猫
1 103 81 叮当2
0 2 0 热门流行
1 31 2 有奖活动
1 32 2 相约香格里拉
1 50 2 新浪彩铃
0 3 0 老歌回放
1 333 3 老电影
1 335 3 怀旧金曲
26 rows selected
一看结果,清晰明了!
CONNECT_BY_ISCYCLE
我们的树状属性一般都是在一条记录中记录一个当前节点的ID和这个节点的父ID来实现。但是,一旦数据中出现了循环记录,如两个节点互为对方父节点,系统就会报ORA-01436错误:
insert into t_tonedirlib(dirindex, fatherindex, dirname, status) values (666, 667, '123', 5);
1 row inserted
insert into t_tonedirlib(dirindex, fatherindex, dirname, status) values (667, 666, '456', 5);
1 row inserted
select dirindex, fatherindex, RPAD(' ', 2*(LEVEL-1)) || dirname from t_tonedirlib
start with fatherindex = 666
connect by fatherindex = prior dirindex
ORA-01436: 用户数据中的 CONNECT BY 循环
<chmetcnv unitname="g" sourcevalue="10" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">10G</chmetcnv>中,可以通过加上NOCYCLE关键字避免报错。并且通过CONNECT_BY_ISCYCLE属性就知道哪些节点产生了循环:
select CONNECT_BY_ISCYCLE, dirindex, fatherindex, RPAD(' ', 2*(LEVEL-1)) || dirname
from t_tonedirlib
start with fatherindex = 666
connect by NOCYCLE fatherindex = prior dirindex
CONNECT_BY_ISCYCLE DIRINDEX FATHERINDEX RPAD(' ',2*(LEVEL-1))||dirname
----------------- ---------------- ---------------------------------
0 667 666 456
1 666 667 123
2 rows selected
以上就是在<chmetcnv unitname="g" sourcevalue="10" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on"><span lang="EN-US">10G</span></chmetcnv>中增强的CONNECT BY了。当然对于这些增强特性的
分享到:
相关推荐
Oracle start with.connect by prior子句实现递归查询
在Oracle中用Start with...Connect By子句递归查询
1.4 Oracle 11g的新特性 1.4.1 数据库管理部分 1.4.2 PL/SQL部分 1.4.3 其他部分 第2章 Oracle在Windows平台上的安装与配置 2.1 Oracle通用安装器 2.2 Oracle数据库软件的安装 2.3 Oracle数据库软件...
NULL 博文链接:https://yunqiang-zhang-hotmail-com.iteye.com/blog/1312354
oracle中 connect by prior 递归算法 Oracle中start with...connect by prior子句用法 connect by 是结构化查询中用到的
·核心概念——oracle database 11g主题呈现在按逻辑组织的章节中 ·主要内容——每章要介绍的具体内容列表 ·实践练习——演示如何应用在每章学到的关键技术 ·学习效果测试——对学习效果的快速自我评估 ...
在Oracle 10g前,FORALL语句的语法只能处理连续性的数组元素。Oracle 10g解决了这两方面的问题,并增加了INDICES OF和VALUES OF子句。本文介绍了这两个子句的语法。
另外,本书还为应用开发人员提供了大量Oracle9i和Oracle 10g新增加的PL/SQL特征。 本书不仅适合于PL/SQL初学者,而且也适合于有经验的PL/SQL编程人员,本书还可以作为Oracle培训班的教材或者辅助材料。 <br>...
oracle11g 第一部分:SQL语言基础 第一章:关系型与非关系型数据库 第二章:SQL的基本函数 第三章:SQL的数据类型 第四章、WHERE子句中常用的运算符 第五章:分组函数 第六章:数据限定和排序 第七章:复杂...
本文是由笔者2012年学习oracle数据库时编写的学习札记,其中的题目 多数为老师留下的思考题目。 我相信本文会对初学者使用oracle有一个初步的使用印象。右图为我所参 考的书籍。 目录 第一讲 Oacle关系数据库 ...
1.4 Oracle 11g的新特性 1.4.1 数据库管理部分 1.4.2 PL/SQL部分 1.4.3 其他部分 第2章 Oracle在Windows平台上的安装与配置 2.1 Oracle通用安装器 2.2 Oracle数据库软件的安装 2.3 Oracle数据库软件的卸载 ...
《Oracle Database 11g初学者指南》能使读者快捷地掌握Oracle Database 11g的基础知识。通过自我评估教程,介绍了核心数据库技术、管理员职责、高可用性以及大型数据库特性。《Oracle Database 11g初学者指南》带领...
《Oracle Database 11g完全参考手册》全面详细地介绍了Oracle Database 11g的强大功能,阐述了如何使用所有的新增功能和工具,如何执行功能强大的SOL查询,如何编写PL/SQL和SQL*Plus语句,如何使用大对象和对象,...
1.4 Oracle 11g的新特性 1.4.1 数据库管理部分 1.4.2 PL/SQL部分 1.4.3 其他部分 第2章 Oracle在Windows平台上的安装与配置 2.1 Oracle通用安装器 2.2 Oracle数据库软件的安装 2.3 Oracle数据库软件的卸载 2.3.1 ...
1.4 Oracle 11g的新特性 1.4.1 数据库管理部分 1.4.2 PL/SQL部分 1.4.3 其他部分 第2章 Oracle在Windows平台上的安装与配置 2.1 Oracle通用安装器 2.2 Oracle数据库软件的安装 2.3 Oracle数据库软件的卸载 2.3.1 ...
对oracle11g中常出现的问题进行总结
Karen Morton及其团队在本书中提供了专业的方案:先掌握语言特性,再学习Oracle为提升语言效率而加入的支持特性,进而将两者综合考虑并在工作中加以应用。作者通过总结各自多年的软件开发和教学培训经验,与大家...