Je wilt zoiets als dit:
select t.table_name, level,lpad(' ', 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
Het probleem met de oorspronkelijke query is dat uc.constraint_name voor de onderliggende tabel de naam is van de externe sleutel. Dat is prima om het eerste kind met de hoofdtabel te verbinden, maar het is niet wat je nodig hebt om de kinderen op het tweede niveau met het eerste te verbinden. Daarom moet je twee keer meedoen tegen de beperkingen in - één keer om de primaire sleutel van de tabel te krijgen, één keer om de externe sleutels te krijgen.
Even terzijde, als je de all_* views gaat opvragen in plaats van de user_* views, dan wil je ze over het algemeen samenvoegen op table_name AND owner, niet alleen table_name. Als meerdere schema's tabellen met dezelfde naam hebben, geeft deelname aan alleen tabelnaam onjuiste resultaten.