25

For a given table 'foo', I need a query to generate a set of tables that have foreign keys that point to foo. I'm using Oracle 10G.

beaver
  • 523
  • 1
  • 9
  • 20
Mark Roddy
  • 27,122
  • 19
  • 67
  • 71
  • 1
    If you just need this info in order to drop the table, you can also use DROP TABLE xx CASCADE CONSTRAINTS – Sten Vesterli Sep 17 '08 at 19:16
  • This article may help: [http://www.databasejournal.com/features/oracle/article.php/3665591](http://www.databasejournal.com/features/oracle/article.php/3665591) – Sean Sep 17 '08 at 18:22

10 Answers10

45

This should work (or something close):

select table_name
from all_constraints
where constraint_type='R'
and r_constraint_name in 
  (select constraint_name
  from all_constraints
  where constraint_type in ('P','U')
  and table_name='<your table here>'); 
Mike Monette
  • 630
  • 6
  • 6
5

The following statement should give the children and all of their descendents. I have tested it on an Oracle 10 database.

SELECT  level, main.table_name  parent,
    link.table_name child
FROM    user_constraints main, user_constraints link    
WHERE   main.constraint_type    IN ('P', 'U')
AND link.r_constraint_name  = main.constraint_name
START WITH main.table_name  LIKE UPPER('&&table_name')
CONNECT BY main.table_name = PRIOR link.table_name
ORDER BY level, main.table_name, link.table_name
yoozer8
  • 7,361
  • 7
  • 58
  • 93
  • nice use of hierarchical retrieval. However when you have tables with self referencing foreign keys, it will generate error. – focusHard Aug 08 '13 at 18:22
  • This is the greatest thing ever. You just need to change the 'U' to 'R' for newer versions of Oracle. – Tom Jun 27 '16 at 17:59
  • @focusHard, I believe that adding `AND main.table_name <> link.table_name` to the where clause will prevent that error. – Tom Jun 27 '16 at 18:09
4

Here's how to take Mike's query one step further to get the column names from the constraint names:

select * from user_cons_columns
where constraint_name in (
  select constraint_name 
  from all_constraints
  where constraint_type='R'
  and r_constraint_name in 
    (select constraint_name
    from all_constraints
    where constraint_type in ('P','U')
    and table_name='<your table name here>'));
matt1616
  • 433
  • 4
  • 8
1

I know it's kinda late to answer but let me answer anyway. Some of the answers above are quite complicated hence here is a much simpler take.

SELECT a.table_name child_table, a.column_name child_column, a.constraint_name, 
b.table_name parent_table, b.column_name parent_column
FROM all_cons_columns a
JOIN all_constraints c ON a.owner = c.owner AND a.constraint_name = c.constraint_name
join all_cons_columns b on c.owner = b.owner and c.r_constraint_name = b.constraint_name
WHERE c.constraint_type = 'R'
AND a.table_name = 'your table name'
Gh61
  • 9,222
  • 4
  • 28
  • 39
arvinq
  • 656
  • 6
  • 12
  • I think this works better:
    select 
      a.table_name child_table, a.column_name child_column, a.constraint_name, b.table_name parent_table, b.column_name parent_column, a.position
    from user_cons_columns a
    join user_constraints c on a.owner = c.owner and a.constraint_name = c.constraint_name
    join user_cons_columns b on c.owner = b.owner and c.r_constraint_name = b.constraint_name and a.position = b.position
    where c.constraint_type = 'R'
    order by a.constraint_name, a.table_name, a.column_name, b.table_name, b.column_name
    – Ravi Wallau Apr 05 '17 at 14:52
  • 1
    When the foreing key is over multiple columns, this query returns invalid results. – Gh61 Mar 22 '21 at 11:11
1

link to Oracle Database Online Documentation

You may want to explore the Data Dictionary views. They have the prefixes:

  • User
  • All
  • DBA

sample:

select * from dictionary where table_name like 'ALL%' 

Continuing Mike's example, you may want to generate scripts to enable/disable the constraints. I only modified the 'select' in the first row.

select  'alter table ' || TABLE_NAME || ' disable constraint ' || CONSTRAINT_NAME || ';'
from all_constraints
where constraint_type='R'
and r_constraint_name in 
  (select constraint_name
  from all_constraints
  where constraint_type in ('P','U')
  and table_name='<your table here>');
Tony R
  • 7,136
  • 4
  • 21
  • 12
0
select distinct table_name, constraint_name, column_name, r_table_name, position, constraint_type 
from (
    SELECT uc.table_name, 
    uc.constraint_name, 
    cols.column_name, 
    (select table_name from user_constraints where constraint_name = uc.r_constraint_name) 
        r_table_name,
    (select column_name from user_cons_columns where constraint_name = uc.r_constraint_name and position = cols.position) 
        r_column_name,
    cols.position,
    uc.constraint_type
    FROM user_constraints uc
    inner join user_cons_columns cols on uc.constraint_name = cols.constraint_name 
    where constraint_type != 'C'
) 
start with table_name = '&&tableName' and column_name = '&&columnName'  
connect by nocycle 
prior table_name = r_table_name 
and prior column_name = r_column_name;   
arco444
  • 22,002
  • 12
  • 63
  • 67
Abu Turab
  • 61
  • 1
  • 3
0
select      acc.table_name, acc.constraint_name 
from        all_cons_columns acc
inner join all_constraints ac
    on acc.constraint_name = ac.constraint_name
where       ac.r_constraint_name in (
    select  constraint_name
    from    all_constraints
    where   table_name='yourTable'
    );
Hiram
  • 409
  • 1
  • 4
  • 13
0

All constraints for one table

select 

    uc.OWNER,
    uc.constraint_name as TableConstraint1,
    uc.r_constraint_name as TableConstraint2,
    uc.constraint_type as constrainttype1,
    us.constraint_type as constrainttype2,
    uc.table_name as Table1,us.table_name as Table2,
    ucc.column_name as TableColumn1, 
    uccs.column_name as TableColumn2
from user_constraints uc
    left outer join user_constraints us on uc.r_constraint_name = us.constraint_name
    left outer join USER_CONS_COLUMNS ucc on ucc.constraint_name = uc.constraint_name
    left outer join USER_CONS_COLUMNS uccs on uccs.constraint_name = us.constraint_name
where uc.OWNER ='xxxx' and uc.table_name='xxxx' 
Mehmet Kurt
  • 161
  • 2
  • 3
0

Adding my two cents here.

This query will return all foreign keys with child and parent columns, matched perfectly even when there is foreign key over multiple columns:

SELECT a.table_name child_table, a.column_name child_column, a.constraint_name, 
b.table_name parent_table, b.column_name parent_column
FROM all_cons_columns a
JOIN all_constraints c ON a.owner = c.owner AND a.constraint_name = c.constraint_name
JOIN all_cons_columns b ON c.owner = b.owner AND c.r_constraint_name = b.constraint_name AND b.position = a.position
WHERE c.constraint_type = 'R'

(inspired by @arvinq aswer)

Gh61
  • 9,222
  • 4
  • 28
  • 39
0

Download the Oracle Reference Guide for 10G which explains the data dictionary tables.

The answers above are good but check out the other tables which may relate to constraints.

SELECT * FROM DICT WHERE TABLE_NAME LIKE '%CONS%';

Finally, get a tool like Toad or SQL Developer which allows you to browse this stuff in a UI, you need to learn to use the tables but you should use a UI also.

Ordiel
  • 2,442
  • 3
  • 36
  • 52
Ethan Post
  • 3,020
  • 3
  • 27
  • 27