设为首页 收藏本站
查看: 640|回复: 0

[经验分享] oracle connect by prior 树形结构

[复制链接]

尚未签到

发表于 2016-7-27 11:04:36 | 显示全部楼层 |阅读模式
为了更好的查询一个树状结构的表,在Oracle的PL/SQL中提供乐一个诱人的特性——CONNECT BY子句。它大大的方便了我们查找树状表:遍历一棵树、寻找某个分支……,但还是存在一些不足。在Oracle 10G,就对这个特性做了增强。下面就举例说明一下:

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 循环

       10G中,可以通过加上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

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-250208-1-1.html 上篇帖子: Oracle about ROUNDING/ROUND_DOWN/ROUND_UP 下篇帖子: Oracle数据库管理员职责(二)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表