Skip to Main Content
  • Questions
  • Create an ALTER - ADD CONSTRAINT SCRIPT.

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Visagan.

Asked: April 17, 2007 - 6:16 am UTC

Last updated: April 18, 2007 - 12:07 pm UTC

Version: 10g

Viewed 10K+ times! This question is

You Asked

I have to write a script(SQL statement only, Not using PL/SQL block(s)) which generates the
1.) ALTER .. ADD CONSTRAINT script for all the tables that REFERENCES any particular table.
2.) ALTER.. ADD CONSTRAINT script for FOREIGN KEY CONSTRAINT for a particular table.

Note: The idea is to generate script for both. i.e. COMPOSITE FOREIGN KEY, as well as SINGLE FOREIGN KEY.

Eg.

SELECT 'ALTER TABLE ' || LOWER(a.table_name)
||' ADD CONSTRAINT ' || LOWER(a.constraint_name)
||' FOREIGN KEY (' || LOWER(column_name) || ') REFERENCES '
|| (SELECT LOWER(table_name) ||'('|| LOWER(column_name) ||')' FROM all_cons_columns
WHERE constraint_name = a.r_constraint_name)
||' INITIALLY DEFERRED DEFERRABLE;'
FROM all_constraints a,
all_cons_columns b
WHERE a.constraint_type ='R'
AND a.table_name = b.table_name
AND a.owner =b.owner
AND a.constraint_name =b.constraint_name
AND a.table_name ='EMP'
AND a.owner= (select user from dual)

Output:

ALTER TABLE emp ADD CONSTRAINT fk_deptno FOREIGN KEY (deptno) REFERENCES dept(deptno) INITIALLY DEFERRED DEFERRABLE;

Problem: The above written query runs fine with SINGLE FOREIGN KEY CONSTRAINT. But this given me an error "ORA-01427: single-row subquery returns more than one row" for COMPOSITE FOREIGN KEY. HOW TO SOLVE THIS?





and Tom said...

I read your first sentence and I reject the premise out of hand.

Why would someone prematurely limit themselves from what might be the most effective, efficient, cheapest approach to a problem???? I'll never, for as long as I live, "get that"

NEVER

So, we have dbms_metadata. It is that dreaded PLSQL stuff, but it is callable from SQL. It would solve this problem.

Or
http://asktom.oracle.com/pls/asktom/f?p=100:11:2402577774283132::::P11_QUESTION_ID:399218963817




Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Does this help?

Will, April 18, 2007 - 4:22 am UTC

I've had to do something similar in the past, and used a query similar to this. It uses an analytic function to create a pivotted column for composite foreign keys. In this case I already knew that such keys had a maximum of 2 columns, but you could probably expand the idea.

It's simplified somewhat to remove some clutter. And probably inefficent, but then I only had to run it once.

Tom, I await your critique!

select
uc.table_name tn,
uc.constraint_name cn,
uc.constraint_type,
uc.r_constraint_name,
ucc.table_name rtn,
ucc.column_name child_column1,
ucc.constraint_name,
ucc.position,
lead(ucc.column_name) over (partition by uc.constraint_name, uc.table_name order by ucc.position) child_column2
from
user_constraints uc
inner join user_cons_columns ucc
on uc.r_constraint_name = ucc.constraint_name and uc.constraint_type = 'R' and uc.owner = ucc.owner
order by uc.table_name, uc.constraint_name, ucc.position
Tom Kyte
April 18, 2007 - 12:07 pm UTC

if it works, it works - I have my script (cons.sql) which I'll continue to use... and dbms_metadata

More to Explore

DBMS_METADATA

More on PL/SQL routine DBMS_METADATA here