[Last Call] Learn about multicloud storage options and how to improve your company's cloud strategy. Register Now

x
?
Solved

Extracting Primary and Foreign Keys

Posted on 2006-07-16
9
Medium Priority
?
966 Views
Last Modified: 2010-08-05
Hi all,

This is more of an SQL question really...

I know I can get the foreign keys of a table by accessing the CONSTRAINTS and CONS_COLUMNS tables, and I know I can then get the matching Primary key of the referenced table by using the referenced Constraint.

Trouble is, I don't know how to put this into a single SQL statement such that I can identify which is which when the query runs. I want to identify the output as

Constraint Name
Primary Key Table
Primary Key Column
Foreign Key Table
Foreign Key Column

but I don't know how to identify each output pair as either a Primary or Foreign Key (the problem being that both are extracted from the same column). I'm guessing a Decode of some sort is required based on the constraint name, but I don't know how to write it.

Can anyone help please?

Many thanks
Gerry
0
Comment
Question by:gamesmeister
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
  • 2
9 Comments
 
LVL 16

Expert Comment

by:Peter Kwan
ID: 17117620
select
c1.constraint_name,
decode(c2.constraint_type, 'R', c3.table_name, c1.table_name) pk_table,
decode(c2.constraint_type, 'R', c3.column_name, c1.column_name) pk_col,
decode(c2.constraint_type, 'R', c1.table_name, null) fk_table,
decode(c2.constraint_type, 'R', c1.column_name, null) fk_col
from
user_cons_columns c1, user_constraints c2, user_cons_columns c3
where c1.constraint_name = c2.constraint_name and c2.r_constraint_name = c3.constraint_name (+)


0
 
LVL 4

Author Comment

by:gamesmeister
ID: 17118454
Thanks for that.

However, while this works for single column foreign keys, in the case of multiple column keys, it doesn't tie up the individual columns on either side i.e.

PKTable A, PKColumns 1 & 2
FKTable B, FKColumns 1 & 2

I'm getting results back that point B.1 to A.2 and vice versa

Any idea how to fix that?

Thanks again
Gerry

0
 
LVL 4

Author Comment

by:gamesmeister
ID: 17118460
Update to the previous post:

I'm getting 4 rows back:

A.1 to B.1
A.2 to B.1
A.1 to B.2
A.2 to B.2

Thanks
Gerry
0
NEW Veeam Agent for Microsoft Windows

Backup and recover physical and cloud-based servers and workstations, as well as endpoint devices that belong to remote users. Avoid downtime and data loss quickly and easily for Windows-based physical or public cloud-based workloads!

 
LVL 16

Expert Comment

by:MohanKNair
ID: 17119532
select a.TABLE_NAME||'.'||c.column_name||' References '||b.table_name val
from all_constraints a, all_constraints b, all_cons_columns c
where a.R_CONSTRAINT_NAME=b.CONSTRAINT_NAME and
a.CONSTRAINT_NAME=c.CONSTRAINT_NAME
and a.CONSTRAINT_TYPE='R'
and a.owner=b.owner
and a.owner=c.owner
/
0
 
LVL 16

Assisted Solution

by:Peter Kwan
Peter Kwan earned 1000 total points
ID: 17119823
how about this?

SELECT
c1.constraint_name,
DECODE(c2.constraint_type, 'R', c3.table_name, c1.table_name) pk_table,
DECODE(c2.constraint_type, 'R', DECODE(c1.position, c3.position, c3.column_name), c1.column_name) pk_col,
DECODE(c2.constraint_type, 'R', c1.table_name, NULL) fk_table,
DECODE(c2.constraint_type, 'R', c1.column_name, NULL) fk_col
FROM
USER_CONS_COLUMNS c1, USER_CONSTRAINTS c2, USER_CONS_COLUMNS c3
WHERE c1.constraint_name = c2.constraint_name AND c2.r_constraint_name = c3.constraint_name (+) AND
DECODE(c2.constraint_type, 'R', DECODE(c1.position, c3.position, c3.column_name), c1.column_name) IS NOT NULL;
0
 
LVL 4

Author Comment

by:gamesmeister
ID: 17126596
Yeah, that works. However, the only thing I would say is that it seems to return many more rows than I need, but that said, I can use code to filter the unwanted rows out (it seems to be returning all columns in a selected table, not just those related to a foreign key).

Mohan, thanks for that. Your statement only picks up the rows I need, but it doesn't give me the primary key column(s). Is it possible to add that to the statement?

Many thanks
Gerry
0
 
LVL 16

Expert Comment

by:MohanKNair
ID: 17127737
select a.TABLE_NAME||'('||
rtrim(max(decode(c.position,1,c.column_name))||','||
max(decode(c.position,2,c.column_name))||','||
max(decode(c.position,3,c.column_name))||','||
max(decode(c.position,4,c.column_name)),',')||') References '||
b.table_name||'('||
rtrim(max(decode(d.position,1,d.column_name))||','||
max(decode(d.position,2,d.column_name))||','||
max(decode(d.position,3,d.column_name))||','||
max(decode(d.position,4,d.column_name)),',')||')'
from all_constraints a, all_constraints b, all_cons_columns c, all_cons_columns d
where a.R_CONSTRAINT_NAME=b.CONSTRAINT_NAME and
a.CONSTRAINT_NAME=c.CONSTRAINT_NAME
and b.CONSTRAINT_NAME=d.CONSTRAINT_NAME
and a.CONSTRAINT_TYPE='R'
and b.CONSTRAINT_TYPE='P'
and a.constraint_name='BOX_OFFICE_DAILY_FK1'
and a.owner=b.owner
and a.owner=c.owner
and a.owner=d.owner
and a.owner='WB2DEV'
group by a.table_name, b.table_name
/


0
 
LVL 16

Accepted Solution

by:
MohanKNair earned 1000 total points
ID: 17127745
Ignore the above post. The correct query is

select a.TABLE_NAME||'('||
rtrim(max(decode(c.position,1,c.column_name))||','||
max(decode(c.position,2,c.column_name))||','||
max(decode(c.position,3,c.column_name))||','||
max(decode(c.position,4,c.column_name)),',')||') References '||
b.table_name||'('||
rtrim(max(decode(d.position,1,d.column_name))||','||
max(decode(d.position,2,d.column_name))||','||
max(decode(d.position,3,d.column_name))||','||
max(decode(d.position,4,d.column_name)),',')||')'
from all_constraints a, all_constraints b, all_cons_columns c, all_cons_columns d
where a.R_CONSTRAINT_NAME=b.CONSTRAINT_NAME and
a.CONSTRAINT_NAME=c.CONSTRAINT_NAME
and b.CONSTRAINT_NAME=d.CONSTRAINT_NAME
and a.CONSTRAINT_TYPE='R'
and b.CONSTRAINT_TYPE='P'
and a.owner=b.owner
and a.owner=c.owner
and a.owner=d.owner
group by a.table_name, b.table_name
/
0
 
LVL 4

Author Comment

by:gamesmeister
ID: 17153867
Outstanding, thank you both very much
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article started out as an Experts-Exchange question, which then grew into a quick tip to go along with an IOUG presentation for the Collaborate confernce and then later grew again into a full blown article with expanded functionality and legacy…
Shell script to create broker configuration file using current broker Configuration, solely for purpose of backup on Linux. Script may need to be modified depending on OS-installation. Please deploy and verify the script in a test environment.
This video shows how to copy a database user from one database to another user DBMS_METADATA.  It also shows how to copy a user's permissions and discusses password hash differences between Oracle 10g and 11g.
Video by: Steve
Using examples as well as descriptions, step through each of the common simple join types, explaining differences in syntax, differences in expected outputs and showing how the queries run along with the actual outputs based upon a simple set of dem…

650 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question