-- constr.sql -- List constraints for a table owned by the current user -- -- Uses types: -- * DB_CONSTRAINT_OT modelled on ALL_CONSTRAINTS record -- * DB_CONSTRAINT_TT collection of DB_CONSTRAINT_OT -- * VARCHAR2_TT generic VARCHAR2 collection. -- Uses bind variables when querying data dictionary. -- Returns results to SQL*Plus as ref cursor. -- -- William Robertson 2003, www.williamrobertson.net /* create or replace type db_constraint_ot as object ( owner varchar2(30) , constraint_name varchar2(30) , constraint_type varchar2(1) , table_name varchar2(30) , search_condition varchar2(32767) , r_owner varchar2(30) , r_constraint_name varchar2(30) , delete_rule varchar2(9) , status varchar2(8) , deferrable varchar2(14) , deferred varchar2(9) , validated varchar2(13) , generated varchar2(14) , bad varchar2(3) , rely varchar2(4) , last_change date , index_owner varchar2(30) , index_name varchar2(30) , invalid varchar2(7) , view_related varchar2(14) ) / create or replace type db_constraint_tt as table of db_constraint_ot / create or replace type varchar2_tt as table of varchar2(4000) / */ def table = &1 set term off store set sqlplus_settings replace ttitle off var tabname varchar2(30) var results refcursor exec :tabname := upper('&table') col table new_value table select upper(:tabname) as "TABLE" from dual; set def on term on autoprint off feed off lines 110 col type hea "Type" col constraint_name hea "Constraint name" col table_name hea "Table name" col table_owner format a20 hea "Owner" col status hea "Status" col deferrable hea "Deferrable?" col deferred hea "Deferred?" col search_condition format a60 word hea "Definition" declare v_table_exists varchar2(1) := 'Y'; v_constraints db_constraint_tt := db_constraint_tt(); cursor c_constraints (cp_tablename all_constraints.table_name%type) is select c.owner , case when c.generated = 'GENERATED NAME' and c.constraint_name like 'SYS\_%' escape '_' then '[' || c.constraint_name || ']' else c.constraint_name end as constraint_name , c.constraint_type , c.table_name , c.search_condition , to_char(null) as column_list , decode(c.constraint_type, 'R', 'Foreign key (%COLS%) to ' || r.table_name || ' (' || c.r_constraint_name || ')' || decode(c.delete_rule, 'CASCADE', ', ' || c.delete_rule), 'P', 'Primary key (%COLS%)', 'U', 'Unique key (%COLS%)' ) key_description , cast ( multiset ( select column_name from all_cons_columns where owner = c.owner and constraint_name = c.constraint_name order by position ) as varchar2_tt ) key_columns , c.r_owner , c.r_constraint_name , c.delete_rule , c.status , c.deferrable , c.deferred , c.validated , c.generated , c.bad , c.rely , c.last_change , c.index_owner , c.index_name , c.invalid , c.view_related from all_constraints c left join all_constraints r on r.constraint_name = c.r_constraint_name and r.owner = c.r_owner where c.table_name = cp_tablename and c.owner = user ; begin for r in c_constraints(:tabname) loop v_constraints.extend; if r.key_columns.count > 0 then for i in r.key_columns.first..r.key_columns.last loop r.column_list := r.column_list || r.key_columns(i) || ', '; end loop; r.column_list := rtrim(r.column_list,', '); end if; r.key_description := replace(r.key_description,'%COLS%', r.column_list); v_constraints(c_constraints%rowcount) := db_constraint_ot ( r.owner , r.constraint_name , r.constraint_type , r.table_name , nvl(r.search_condition,r.key_description) , r.r_owner , r.r_constraint_name , r.delete_rule , r.status , r.deferrable , r.deferred , r.validated , r.generated , r.bad , r.rely , r.last_change , r.index_owner , r.index_name , r.invalid , r.view_related ); end loop; if v_constraints.count = 0 then -- nothing in all_constraints - check table exists: select min('N') into v_table_exists from dual where not exists ( select 1 from all_tables where table_name = :tabname and owner = user ); if v_table_exists = 'N' then dbms_output.put_line('No such table "' || :tabname || '"'); end if; end if; open :results for select case when search_condition like '"%" IS NOT NULL' then 'Not Null' when constraint_type = 'C' then 'Check' when constraint_type = 'U' then 'Unique' when constraint_type = 'P' then 'Primary' when constraint_type = 'R' then 'FK' else constraint_type end as type , constraint_name , search_condition , status from table(v_constraints) order by case when constraint_type = 'P' then '1' when constraint_type = 'U' then '2' when constraint_type = 'R' then '3' when constraint_type like '"%" IS NOT NULL' then '4' when constraint_type = 'C' then '5' else constraint_type end , constraint_name; end; / set term on print :results ttitle on left 'Tables referencing &table:' skip1 select -- r_owner as table_owner table_name , constraint_name , status , deferrable , deferred from all_constraints where constraint_type = 'R' and r_owner = user and r_constraint_name in ( select constraint_name from user_constraints where table_name = :tabname and constraint_type in ('P','U') ); prompt ttitle "" ttitle off @sqlplus_settings.sql