oracle – 表依赖的递归查询不会像我想的那样递归

我有一个想法,我可以编写一个查询来查找根表的所有后代表,基于外键.

查询看起来像这样:

select level,lpad(' ',2 * (level - 1)) || uc.table_name as "TABLE",uc.constraint_name,uc.r_constraint_name
from all_constraints uc
where uc.constraint_type in ('R','P')
start with uc.table_name = 'ROOT_TAB'
connect by nocycle prior uc.constraint_name = uc.r_constraint_name
order by level asc;

结果我看起来像这样:

        1   ROOT_TAB        XPKROOTTAB  
        1   ROOT_TAB        R_20           XPKPART_TAB
        2     CHILD_TAB_1   R_40           XPKROOTTAB
        2     CHILD_TAB_2   R_115          XPKROOTTAB
        2     CHILD_TAB_3   R_50           XPKROOTTAB

此结果是ROOT_TAB的所有子表,但查询不会递归到CHILD_TAB_1,CHILD_TAB_2或CHILD_TAB_3的子项.

递归查询对我来说是新的,所以我猜我在connect by子句中缺少一些东西,但我在这里画一个空白.实际上是否可以在单个查询中获得ROOT_TAB的完整层次结构,或者我最好在递归过程中包装查询?

解决方法

你想要这样的东西:

select t.table_name,level,2 * (level - 1))||t.table_name 
from user_tables t
join user_constraints c1 
    on (t.table_name = c1.table_name 
    and c1.constraint_type in ('U','P'))
left join user_constraints c2 
    on (t.table_name = c2.table_name 
    and c2.constraint_type='R')
start with t.table_name = 'ROOT_TAB'
connect by prior c1.constraint_name = c2.r_constraint_name

原始查询的问题是子表的uc.constraint_name是外键的名称.这对于将第一个子节点连接到根表是很好的,但是不需要将第二个节点上的子节点连接到第一个节点.这就是为什么你需要连接两次约束 – 一次获取表的主键,一次获取外键.

顺便说一句,如果您要查询all_ *视图而不是user_ *视图,通常需要将它们连接到table_name AND owner,而不仅仅是table_name.如果多个模式具有相同名称的表,则仅加入table_name将得到不正确的结果.

相关文章

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注