Chcesz coś takiego:
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
Problem z pierwotnym zapytaniem polega na tym, że uc.constraint_name dla tabeli podrzędnej jest nazwą klucza obcego. Jest to dobre dla połączenia pierwszego dziecka z tabelą główną, ale nie jest to tym, czego potrzebujesz, aby połączyć dzieci z drugiego poziomu z pierwszym. Dlatego musisz dwukrotnie połączyć się wbrew ograniczeniom — raz, aby uzyskać klucz podstawowy tabeli, drugi, aby uzyskać klucze obce.
Na marginesie, jeśli zamierzasz wysyłać zapytania do widoków all_*, a nie widoków user_*, zazwyczaj chcesz dołączyć do nich na nazwa_tabeli ORAZ właściciel, a nie tylko nazwa_tabeli. Jeśli wiele schematów ma tabele o tej samej nazwie, połączenie tylko w tabeli nazwa_tabeli da nieprawidłowe wyniki.