I want to write an SQL to check out FK'S. What I got so far:
SELECT OWNER,
CONSTRAINT_TYPE,
TABLE_NAME,
R_OWNER,
R_CONSTRAINT_NAME
FROM ALL_CONSTRAINTS
WHERE OWNER = 'XXX'
AND TABLE_NAME = 'XXX'
AND CONSTRAINT_TYPE = 'R'
The problem: I don't see where the FK is mapping to. You have R_OWNER and R_CONSTRAINT_NAME, but no R_TABLE. Is there anyway this can be done by writing SQL?
UPDATED.
This gives you what you want:
select
cc.owner,
cc.constraint_name,
cc.table_name,
cc.column_name,
c.r_owner,
c_pk.table_name r_table_name,
c_pk.constraint_name r_pk
from all_cons_columns cc
join all_constraints c on cc.owner = c.owner and cc.constraint_name = c.constraint_name
join all_constraints c_pk on c.r_owner = c_pk.owner and c.r_constraint_name = c_pk.constraint_name
where c.constraint_type = 'R'
and cc.owner = 'XXX'
and cc.table_name = 'XXX';
You can get list of all existing foreign keys :
SELECT RC.CONSTRAINT_NAME FK_Name,
KF.TABLE_SCHEMA FK_Schema,
KF.TABLE_NAME FK_Table,
KF.COLUMN_NAME FK_Column,
RC.UNIQUE_CONSTRAINT_NAME PK_Name,
KP.TABLE_SCHEMA PK_Schema,
KP.TABLE_NAME PK_Table,
KP.COLUMN_NAME PK_Column,
RC.MATCH_OPTION MatchOption,
RC.UPDATE_RULE UpdateRule,
RC.DELETE_RULE DeleteRule
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KF ON RC.CONSTRAINT_NAME = KF.CONSTRAINT_NAME
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KP ON RC.UNIQUE_CONSTRAINT_NAME = KP.CONSTRAINT_NAME;
I was studying tis question - How can I find which tables reference a given table in Oracle SQL Developer? ,
And It showed some code to find which tables reference a specified table :
elect table_name, constraint_name, status, owner
from all_constraints
where r_owner = :r_owner
and constraint_type = 'R'
and r_constraint_name in
(
select constraint_name from all_constraints
where constraint_type in ('P', 'U')
and table_name = :r_table_name
and owner = :r_owner
)
order by table_name, constraint_name
So I'm trying to tailor the code to get the tables that refer to a specific column (here , PREPARER_ID ) ; this is what I tried so far :
select column_name, constraint_name, status, owner
from all_constraints
where r_owner = :r_owner
and constraint_type = 'R'
and r_constraint_name in
(
select constraint_name from all_constraints
where constraint_type in ('P', 'U')
and column_name = :r_column_name
and owner = :r_owner
)
ORDER BY column_name, constraint_name
This gives me an error :
ORA-00904: "COLUMN_NAME": invalid identifier
00904. 00000 - "%s: invalid identifier"
*Cause:
*Action:
Error at Line: 103 Column: 8
To query based on the column you need to look at the all_cons_columns view, as well as all_constraints. This doesn't have to use a subquery but following your pattern:
select ac.table_name, acc.column_name, ac.constraint_name, ac.status, ac.owner
from all_constraints ac
join all_cons_columns acc
on acc.owner = ac.owner
and acc.constraint_name = ac.constraint_name
and acc.table_name = ac.table_name
where ac.r_owner = :r_owner
and ac.constraint_type = 'R'
and ac.r_constraint_name in
(
select ac2.constraint_name
from all_constraints ac2
join all_cons_columns acc2
on acc2.owner = ac2.owner
and acc2.constraint_name = ac2.constraint_name
and acc2.table_name = ac2.table_name
where ac2.constraint_type in ('P', 'U')
and acc2.column_name = :r_column_name
and ac2.owner = :r_owner
)
ORDER BY ac.table_name, acc.column_name, acc.constraint_name;
With a sample set-up:
create table parent_table (preparer_id number primary key);
create table child_table (some_col number references parent_table(preparer_id));
And bind settings:
var r_column_name varchar2(30);
var r_owner varchar2(30);
begin
:r_column_name := 'PREPARER_ID';
:r_owner := user;
end;
/
That gets:
TABLE_NAME COLUMN_NAME CONSTRAINT_NAME STATUS OWNER
-------------------- -------------------- -------------------- -------- ----------
CHILD_TABLE SOME_COL SYS_C00101337 ENABLED MY_SCHEMA
I'm trying to get the index_name, constraint_type and uniqueness of index based on the below query:
select constraint_name index_name,
'P',
'U'
from all_constraints
where owner = 'owner_name'
and table_name = 'table_name'
and constraint_type = 'P'
UNION
select index_name,
' ',
substr(uniqueness,1,1)
from all_indexes
where owner = 'owner_name'
and table_name = 'table_name'
and index_name not in (
select constraint_name
from all_constraints
where owner = 'owner_name'
and table_name = 'table_name'
)
order by index_name
Now, I need to get the column_name corresponding to the index_name retrieved from the above query using the following queries:
If index is Primary (P):
select column_name
from all_cons_columns
where owner = 'owner_name' and constraint_name = 'index_name'
If index is not primary:
select column_name
from all_ind_columns
where index_owner = 'owner_name' and index_name = 'index_name'
Is there any way i can join the queries to get the column_name alongside each index_name? I need the duplicate entries for index_name if the index if built on multiple columns.
I've tried different joins but none seem to work in my case. Any ideas?
Don't know if this is exactly what you need.
> SELECT DECODE(PRIM
> ,'P',(select column_name
> from all_ind_columns
> where index_owner = ta.owner and index_name= ta.index_name)
> , (select column_name
> from all_cons_columns
> where owner = ta.owner and constraint_name = ta.index_name) ), index_name from ( select constraint_name index_name,
> 'P' PRIM,
> 'U' UNIQ,
> owner,
> table_name from all_constraints where constraint_type = 'P' and owner = 'OWNER_NAME' and table_name = 'TABLE_NAME' UNION select
> index_name,
> ' ',
> substr(uniqueness,1,1),
> owner,
> table_name from all_indexes where owner = 'OWNER_NAME' and table_name = 'TABLE_NAME'
> and index_name not in (
> select constraint_name
> from all_constraints
> where owner = 'OWNER_NAME'
> and table_name = 'TABLE_NAME'
> ) order by index_name ) TA
I've got an Oracle-DB with ~50 Tables.
Now, i'm looking for all tables with a foreign key to Table 'xyz'.
is there a way to do this?
greetings,
Lea
Foreign keys reference primary (or unique) keys, not tables. So first thing is to establish the primary key(s) for XYZ. Then we can look up the foreign keys which reference it.
select p.constraint_name
, p.constraint_type
, f.owner
, f.table_name
, f.constraint_name
from all_constraints p
left join all_constraints f
on ( f.r_constraint_name = p.constraint_name)
where p.table_name = 'XYZ'
and p.constraint_type in ('P', 'U')
and f.constraint_type = 'R'
I've done this as an OUTER JOIN so it will return something even if no tables reference a key on XYZ. Your table might be referenced by tables in other schemas. That's why I suggest using ALL_CONSTRAINTS rather than USER_CONSTRAINTS.
select fk.table_name from all_constraints fk , all_constraints pk
where
pk.table_name = 'XYZ'
and fk.constraint_type = 'R'
and fk.r_constraint_name = pk.constraint_name
It seems, that you can query User_Constraints view, something like
select distinct Table_Name
from User_Constraints
where Constraint_Type = 'R' and
R_Constraint_Name in (
select Constraint_Name
from User_Constraints
where Constraint_Type = 'P' and
Table_Name = Upper('xyz')) -- <- Your table name
order by Table_Name -- <- may be redundant
for sql try this :
SELECT K.TABLE_NAME ,
K.COLUMN_NAME ,
K.CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS C
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS K ON C.TABLE_NAME = K.TABLE_NAME
AND C.CONSTRAINT_CATALOG = K.CONSTRAINT_CATALOG
AND C.CONSTRAINT_SCHEMA = K.CONSTRAINT_SCHEMA
AND C.CONSTRAINT_NAME = K.CONSTRAINT_NAME
WHERE C.CONSTRAINT_TYPE = 'FOREIGN KEY' /*FOR FOREIGN KEY U NEED TO REPLACE CONSTRAINT_TYPE WITH FOREIGN KEY*/
AND K.COLUMN_NAME IN ( SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS )
In Oracle SQL Developer, if I'm viewing the information on a table, I can view the constraints, which let me see the foreign keys (and thus which tables are referenced by this table), and I can view the dependencies to see what packages and such reference the table. But I'm not sure how to find which tables reference the table.
For example, say I'm looking at the emp table. There is another table emp_dept which captures which employees work in which departments, which references the emp table through emp_id, the primary key of the emp table. Is there a way (through some UI element in the program, not through SQL) to find that the emp_dept table references the emp table, without me having to know that the emp_dept table exists?
No. There is no such option available from Oracle SQL Developer.
You have to execute a query by hand or use other tool (For instance PLSQL Developer has such option). The following SQL is that one used by PLSQL Developer:
select table_name, constraint_name, status, owner
from all_constraints
where r_owner = :r_owner
and constraint_type = 'R'
and r_constraint_name in
(
select constraint_name from all_constraints
where constraint_type in ('P', 'U')
and table_name = :r_table_name
and owner = :r_owner
)
order by table_name, constraint_name
Where r_owner is the schema, and r_table_name is the table for which you are looking for references. The names are case sensitive
Be careful because on the reports tab of Oracle SQL Developer there is the option "All tables / Dependencies" this is from ALL_DEPENDENCIES which refers to "dependencies between procedures, packages, functions, package bodies, and triggers accessible to the current user, including dependencies on views created without any database links.". Then, this report have no value for your question.
To add this to SQL Developer as an extension do the following:
Save the below code into an xml file (e.g. fk_ref.xml):
<items>
<item type="editor" node="TableNode" vertical="true">
<title><![CDATA[FK References]]></title>
<query>
<sql>
<![CDATA[select a.owner,
a.table_name,
a.constraint_name,
a.status
from all_constraints a
where a.constraint_type = 'R'
and exists(
select 1
from all_constraints
where constraint_name=a.r_constraint_name
and constraint_type in ('P', 'U')
and table_name = :OBJECT_NAME
and owner = :OBJECT_OWNER)
order by table_name, constraint_name]]>
</sql>
</query>
</item>
</items>
Add the extension to SQL Developer:
Tools > Preferences
Database > User Defined Extensions
Click "Add Row" button
In Type choose "EDITOR", Location is where you saved the xml file above
Click "Ok" then restart SQL Developer
Navigate to any table and you should now see an additional tab next to SQL one, labelled FK References, which displays the new FK information.
Reference
http://www.oracle.com/technetwork/issue-archive/2007/07-jul/o47sql-086233.html
Replace [Your TABLE] with emp in the query below
select owner,constraint_name,constraint_type,table_name,r_owner,r_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]');
You may be able to query this from the ALL_CONSTRAINTS view:
SELECT table_name
FROM ALL_CONSTRAINTS
WHERE constraint_type = 'R' -- "Referential integrity"
AND r_constraint_name IN
( SELECT constraint_name
FROM ALL_CONSTRAINTS
WHERE table_name = 'EMP'
AND constraint_type IN ('U', 'P') -- "Unique" or "Primary key"
);
SQL Developer 4.1, released in May of 2015, added a Model tab which shows table foreign keys which refer to your table in an Entity Relationship Diagram format.
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;
This has been in the product for years - although it wasn't in the product in 2011.
But, simply click on the Model page.
Make sure you are on at least version 4.0 (released in 2013) to access this feature.
How about something like this:
SELECT c.constraint_name, c.constraint_type, c2.constraint_name, c2.constraint_type, c2.table_name
FROM dba_constraints c JOIN dba_constraints c2 ON (c.r_constraint_name = c2.constraint_name)
WHERE c.table_name = <TABLE_OF_INTEREST>
AND c.constraint_TYPE = 'R';
To add to the above answer for sql developer plugin, using the below xml will help in getting the column associated with the foreign key.
<items>
<item type="editor" node="TableNode" vertical="true">
<title><![CDATA[FK References]]></title>
<query>
<sql>
<![CDATA[select a.owner,
a.constraint_name,
a.table_name,
b.column_name,
a.status
from all_constraints a
join all_cons_columns b ON b.constraint_name = a.constraint_name
where a.constraint_type = 'R'
and exists(
select 1
from all_constraints
where constraint_name=a.r_constraint_name
and constraint_type in ('P', 'U')
and table_name = :OBJECT_NAME
and owner = :OBJECT_OWNER)
order by table_name, constraint_name]]>
</sql>
</query>
</item>
</items>
I like to do this with a straight SQL query, rather than messing about with the SQL Developer application.
Here's how I just did it. Best to read through this and understand what's going on, so you can tweak it to fit your needs...
WITH all_primary_keys AS (
SELECT constraint_name AS pk_name,
table_name
FROM all_constraints
WHERE owner = USER
AND constraint_type = 'P'
)
SELECT ac.table_name || ' table has a foreign key called ' || upper(ac.constraint_name)
|| ' which references the primary key ' || upper(ac.r_constraint_name) || ' on table ' || apk.table_name AS foreign_keys
FROM all_constraints ac
LEFT JOIN all_primary_keys apk
ON ac.r_constraint_name = apk.pk_name
WHERE ac.owner = USER
AND ac.constraint_type = 'R'
AND ac.table_name = nvl(upper(:table_name), ac.table_name)
ORDER BY ac.table_name, ac.constraint_name
;
Only Replace table_name with your primary table name
select *
from all_constraints
where r_constraint_name in (
select constraint_name
from all_constraints
where table_name='table_name'
);
Replace MY_OWNER_NAME and MY_TABLE_NAME below and you are ready to go RECURSIVELY:
DECLARE
FUNCTION list_all_child_tables_and_constraints(asked_table_name in VARCHAR2, parent_table_name in VARCHAR2)
RETURN VARCHAR2 IS
current_path VARCHAR2(100);
BEGIN
FOR item IN
(SELECT fk.TABLE_NAME, constraint_parent.FK FK1, constraint_child.FK FK2
FROM all_constraints fk, all_constraints pk,
(SELECT acc.CONSTRAINT_NAME, LISTAGG(acc.COLUMN_NAME, ', ') WITHIN GROUP (ORDER BY acc.COLUMN_NAME) AS FK
FROM ALL_CONS_COLUMNS acc
WHERE acc.OWNER = 'MY_OWNER_NAME'
GROUP BY acc.CONSTRAINT_NAME) constraint_parent,
(SELECT acc.CONSTRAINT_NAME, LISTAGG(acc.COLUMN_NAME, ', ') WITHIN GROUP (ORDER BY acc.COLUMN_NAME) AS FK
FROM ALL_CONS_COLUMNS acc
WHERE acc.OWNER = 'MY_OWNER_NAME'
GROUP BY acc.CONSTRAINT_NAME) constraint_child
WHERE pk.owner = fk.r_owner
AND pk.constraint_name = fk.r_constraint_name
AND fk.constraint_type = 'R'
AND pk.table_name = asked_table_name
AND constraint_parent.CONSTRAINT_NAME = fk.CONSTRAINT_NAME
AND constraint_child.CONSTRAINT_NAME = fk.R_CONSTRAINT_NAME
AND pk.owner = 'MY_OWNER_NAME'
AND fk.owner = 'MY_OWNER_NAME')
LOOP
current_path := parent_table_name || ' // ' || item.TABLE_NAME;
DBMS_OUTPUT.PUT_LINE(current_path);
DBMS_OUTPUT.PUT_LINE(' [' || item.FK1 || '] [' || item.FK2 || ']');
DBMS_OUTPUT.PUT_LINE('');
current_path := list_all_child_tables_and_constraints(item.TABLE_NAME, current_path);
END LOOP;
RETURN '-----------FINISHED-----------';
EXCEPTION
WHEN OTHERS THEN
RETURN '-----------FINISHED-----------';
END list_all_child_tables_and_constraints;
BEGIN
DBMS_OUTPUT.PUT_LINE(list_all_child_tables_and_constraints('MY_TABLE_NAME', ''));
END;