Search This Blog

Total Pageviews

Friday, 11 November 2011

Oracle Primary key Foreign Key report

 

Oracle Primary key Foreign Key report
oracle pk key fk key
Oracle pk fk
Listing Table Dependencies ( Foreign Key References )

==================
 https://anuj-singh.blogspot.com/2025/    ORA-02292: integrity constraint violated - child record found
=======================
set feed off

set pagesize 10000
ttitle off
--
ttitle left'primary and foreign key relationsships' skip 2
set feed off
set pagesize 10000

--

column datum new_value datum noprint
column for_owner format a5 heading 'table|owner'
column pri_tsname format a10 heading 'tablespace'
column for_table format a17 heading 'from|foreign|table'
column for_col format a16 heading 'from|foreign|column'
column pri_table format a17 heading 'to|primary|table'
column pri_col format a16 heading 'to|primary|column'

break on for_owner skip 1

select
a.owner for_owner,
e.tablespace_name pri_tsname,
a.table_name for_table,
c.column_name for_col,
b.table_name pri_table,
d.column_name pri_col
from dba_constraints a,
dba_constraints b,
dba_cons_columns c,
dba_cons_columns d,
dba_tables e
where a.owner in ('SCOTT') ------- <<<<<<<<<<<<<<
and a.r_constraint_name = b.constraint_name
and a.constraint_type = 'R'
and b.constraint_type = 'P'
and a.r_owner = b.owner
and a.constraint_name = c.constraint_name
and a.owner = c.owner
and a.table_name = c.table_name
and b.constraint_name = d.constraint_name
and b.owner = d.owner
and b.table_name = d.table_name
and b.table_name = e.table_name
order by a.owner,a.table_name;



primary and foreign key relationsships

from from to to
table foreign foreign primary primary
owner tablespace table column table column
----- ---------- ----------------- ---------------- ----------------- ----------------
SCOTT EXAMPLE ORDER_LINES ORDER_ID ORDERS ID
USERS ORDER_LINES ORDER_ID ORDERS ID
SYSTEM ORDER_LINES ORDER_ID ORDERS ID



=================================


CLEAR COLUMNS
CLEAR BREAK
SET PAUSE ON
SET FEEDBACK OFF
SET PAGESIZE 20
COLUMN "This Table References Fk" FORMAT A30
COLUMN "This Table Pk" FORMAT A30
BREAK ON "This Table References Fk" SKIP 2

SPOOL TAB_DEPEND.txt
SELECT A.TABLE_NAME "This Table References Fk", DECODE( A.R_OWNER, A.OWNER, B.TABLE_NAME, A.R_OWNER || '.' || B.TABLE_NAME ) "This Table Pk"
FROM USER_CONSTRAINTS A, USER_CONSTRAINTS B
WHERE A.R_CONSTRAINT_NAME = B.CONSTRAINT_NAME
AND A.CONSTRAINT_TYPE ='R'
AND B.CONSTRAINT_TYPE IN ( 'U', 'P' )
GROUP BY A.TABLE_NAME,DECODE( A.R_OWNER, A.OWNER, B.TABLE_NAME,A.R_OWNER || '.' || B.TABLE_NAME )
ORDER BY 1, 2
/

SQL> connect scott/tiger

Connected.
SQL> ed pkfk1

SQL> @pkfk1



primary and foreign key relationsships

This Table References Fk This Table Pk
------------------------------ ------------------------------
ORDER_LINES ORDERS

===============================================


set linesize 300 pagesize 300
col FK_TABLE for a20
col FK_COLUMN  for a20
col PK_TABLE   for a24
col PK_COLUMN  for a24
col CONSTRAINT_NAME  for a20
col owner for a15
 
 WITH
reference_view AS
     (SELECT a.owner, a.table_name, a.constraint_name, a.constraint_type,  a.r_owner, a.r_constraint_name, b.column_name
        FROM dba_constraints a, dba_cons_columns b
       WHERE 
          a.owner = b.owner
         AND a.constraint_name = b.constraint_name
         AND constraint_type = 'R'),
constraint_view AS
     (SELECT a.owner a_owner, a.table_name, a.column_name, b.owner b_owner,  b.constraint_name
        FROM dba_cons_columns a, dba_constraints b
       WHERE a.owner = b.owner
         AND a.constraint_name = b.constraint_name
         AND b.constraint_type = 'P'
         ) ,
usertableviewlist AS 
(
      select  TABLE_NAME  from dba_tables  
) 
SELECT  
   distinct rv.owner,   rv.table_name FK_Table , rv.column_name FK_Column ,  CV.table_name PK_Table , rv.column_name PK_Column , rv.r_constraint_name Constraint_Name 
  FROM reference_view rv, constraint_view CV , usertableviewlist UTable
 WHERE rv.r_constraint_name = CV.constraint_name 
 AND rv.r_owner = CV.b_owner 
 And UTable.TABLE_NAME = rv.table_name
 and rv.column_name='DEPTNO' 
 and rv.owner='SYS'
 ; 
 
 
OWNER           FK_TABLE             FK_COLUMN            PK_TABLE                 PK_COLUMN                CONSTRAINT_NAME
--------------- -------------------- -------------------- ------------------------ ------------------------ --------------------
SYS             EMP1                 DEPTNO               DEPT                     DEPTNO                   PK_DEPT
SYS             EMP                  DEPTNO               DEPT                     DEPTNO                   PK_DEPT
SYS             EMP2                 DEPTNO               DEPT                     DEPTNO                   PK_DEPT


	
set linesize 300
col	PKTABLE_SCHEM     for a15                                                                                                               
col		PKTABLE_NAME   for a15 
col		PKCOLUMN_NAME   for a15 
col		FKTABLE_NAME   for a15 
col		FKTABLE_SCHEM   for a15 
col		FKCOLUMN_NAME   for a15 
col		FK_NAME   for a15 
col PK_NAME for a15

	SELECT NULL AS pktable_cat,
       p.owner as pktable_schem,
       p.table_name as pktable_name,
       pc.column_name as pkcolumn_name,
       NULL as fktable_cat,
       f.owner as fktable_schem,
       f.table_name as fktable_name,
       fc.column_name as fkcolumn_name,
       fc.position as key_seq,
       NULL as update_rule,
       decode (f.delete_rule, 'CASCADE', 0, 'SET NULL', 2, 1) as delete_rule,
       f.constraint_name as fk_name,
       p.constraint_name as pk_name,
       decode(f.deferrable,       'DEFERRABLE',5      ,'NOT DEFERRABLE',7      , 'DEFERRED', 6      ) deferrability 
      FROM all_cons_columns pc, all_constraints p,
      all_cons_columns fc, all_constraints f
WHERE 1 = 1
  AND f.table_name = 'EMP' ----<<<
  AND f.owner = 'SYS'   ---<<<
  AND f.constraint_type = 'R'
  AND p.owner = f.r_owner
  AND p.constraint_name = f.r_constraint_name
  AND p.constraint_type = 'P' -- This is the problem
  AND pc.owner = p.owner
  AND pc.constraint_name = p.constraint_name
  AND pc.table_name = p.table_name
  AND fc.owner = f.owner
  AND fc.constraint_name = f.constraint_name
  AND fc.table_name = f.table_name
  AND fc.position = pc.position
ORDER BY pktable_schem, pktable_name, key_seq



P PKTABLE_SCHEM   PKTABLE_NAME    PKCOLUMN_NAME   F FKTABLE_SCHEM   FKTABLE_NAME    FKCOLUMN_NAME      KEY_SEQ U DELETE_RULE FK_NAME         PK_NAME         DEFERRABILITY
- --------------- --------------- --------------- - --------------- --------------- --------------- ---------- - ----------- --------------- --------------- -------------
  SYS             DEPT            DEPTNO            SYS             EMP             DEPTNO                   1             1 FK_DEPTNO       PK_DEPT                     7



========================================

col TABLE_NAME  for a15
col COLUMN_NAME   for a15
col R_TABLE_NAME   for a15
col R_OWNER   for a15
col R_COLUMN_NAME   for a15
col R_CONSTRAINT_NAME   for a15

with cons as
  (select c.owner, c.constraint_name, c.constraint_type, c.table_name, c.r_owner, c.r_constraint_name, cc.column_name, cc.position
       from   dba_constraints c, dba_cons_columns cc
       where  (Not ((c.constraint_name like 'BIN$%==$0') and length(c.constraint_name) = 30))
       and      (    c.constraint_type = 'R' 
              -- and ((c.owner = sys_context('USERENV', 'CURRENT_SCHEMA')) or (c.r_owner = sys_context('USERENV', 'CURRENT_SCHEMA')))
			--and   c.owner='SYS'
               and c.owner = cc.owner 
               and c.constraint_name = cc.constraint_name
               )
       or     (    c.constraint_type in ('P', 'U') 
              -- and c.owner = sys_context('USERENV', 'CURRENT_SCHEMA')
               and c.owner = cc.owner
               and c.constraint_name = cc.constraint_name))
select 
         'REF_INTEGRITY'             AS type,
         ref_cons.owner,
         ref_cons.table_name,
         ref_cons.column_name,
         ref_cons.constraint_name,
         pk_cons.owner              as r_owner,
         pk_cons.table_name         AS r_table_name,
         pk_cons.column_name        AS r_column_name,
         pk_cons.constraint_name    AS r_constraint_name
    FROM cons ref_cons,
         cons pk_cons
   WHERE  ref_cons.constraint_type = 'R' 
    and   pk_cons.constraint_type in ('P', 'U') 
    and   pk_cons.owner in (ref_cons.r_owner, ref_cons.owner)
    AND   ref_cons.r_constraint_name = pk_cons.constraint_name
    AND   ref_cons.position = pk_cons.position
	and pk_cons.table_name='DEPT'
	and pk_cons.owner='SYS'
ORDER BY ref_cons.owner,
         ref_cons.table_name,
         ref_cons.constraint_name,
         ref_cons.position;


TYPE          OWNER           TABLE_NAME      COLUMN_NAME     CONSTRAINT_NAME      R_OWNER         R_TABLE_NAME    R_COLUMN_NAME   R_CONSTRAINT_NA
------------- --------------- --------------- --------------- -------------------- --------------- --------------- --------------- ---------------
REF_INTEGRITY SYS             EMP             DEPTNO          FK_DEPTNO            SYS             DEPT            DEPTNO          PK_DEPT
REF_INTEGRITY SYS             EMP1            DEPTNO          FK_DEPTNO1           SYS             DEPT            DEPTNO          PK_DEPT
REF_INTEGRITY SYS             EMP2            DEPTNO          FK_DEPTNO2           SYS             DEPT            DEPTNO          PK_DEPT


====
set linesize 300
col XCOLUMNS for a20
col R_COLUMNS for a20
col type for a8
col TABLE_NAME for a29
select	rcon.owner as r_owner, rcon.constraint_name as r_constraint_name, rcon.table_name as r_table_name, 
			listagg (rcol.column_name, ', ') WITHIN GROUP (ORDER BY rcol.owner, rcol.table_name, rcol.constraint_name) R_COLUMNS,
			rcon.constraint_type as type,	con.owner, con.table_name, con.constraint_name,  
			listagg (col.column_name, ', ') WITHIN GROUP (ORDER BY col.owner, col.table_name, col.constraint_name) XCOLUMNS
		from 	all_constraints rcon
			join all_cons_columns rcol	on rcol.owner=rcon.owner and rcol.table_name=rcon.table_name and rcol.constraint_name=rcon.constraint_name	
			left join all_constraints con 	on rcon.owner = con.r_owner and rcon.constraint_name = con.r_constraint_name
			left join all_cons_columns col	on col.owner=con.owner and col.table_name=con.table_name and col.constraint_name=con.constraint_name
			and rcol.position = col.position
		where rcon.owner = upper('XXXX') 
and rcon.table_name = upper('TTTTTT') 
--and rcon.constraint_type in ('P','U') 
			--and rcon.constraint_name = nvl(upper(p_constraint),rcon.constraint_name) 
--and rcon.status = 'ENABLED'
		group by rcon.owner, rcon.constraint_name, rcon.table_name, rcon.constraint_type,con.owner, con.table_name, con.constraint_name
		order by rcon.owner, rcon.constraint_name, rcon.constraint_type;

 


define O='ANUJ'
define T='DEPT'
SET linesize 300 pagesize 200
COL PARENT_TABLE       FOR A25
COL CHILD_TABLE        FOR A25
COL CHILD_FK_COLUMN    FOR A25
COL PARENT_PK_COLUMN   FOR A25
COL FK_CONSTRAINT_NAME FOR A30
COL PK_CONSTRAINT_NAME FOR A30
COL PARENT_OWNER       FOR A15
COL CHILD_OWNER        FOR A15
COL LEVEL_NO           FOR 999
WITH recursive_fks (
    parent_table,
    child_table,
    child_fk_column,
    parent_pk_column,
    fk_constraint_name,
    pk_constraint_name,
    parent_owner,
    child_owner,
    level_no
) AS (
    -- Level 0: direct children of starting table
    SELECT 
        ac_parent.table_name        AS parent_table,
        ac_child.table_name         AS child_table,
        acc_child.column_name       AS child_fk_column,
        acc_parent.column_name      AS parent_pk_column,
        ac_child.constraint_name    AS fk_constraint_name,
        ac_parent.constraint_name   AS pk_constraint_name,
        ac_parent.owner             AS parent_owner,
        ac_child.owner              AS child_owner,
        0                           AS level_no
    FROM all_constraints ac_child
    JOIN all_cons_columns acc_child
      ON ac_child.constraint_name = acc_child.constraint_name
     AND ac_child.owner = acc_child.owner
    JOIN all_constraints ac_parent
      ON ac_child.r_constraint_name = ac_parent.constraint_name
     AND ac_child.r_owner = ac_parent.owner
    JOIN all_cons_columns acc_parent
      ON ac_parent.constraint_name = acc_parent.constraint_name
     AND ac_parent.owner = acc_parent.owner
     AND acc_parent.position = acc_child.position
    WHERE ac_parent.table_name = '&T'
      AND ac_parent.owner = '&O'
      AND ac_child.constraint_type = 'R'
    UNION ALL
    -- Recursive: follow relationships downwards
    SELECT
        ac_parent.table_name,
        ac_child.table_name,
        acc_child.column_name,
        acc_parent.column_name,
        ac_child.constraint_name,
        ac_parent.constraint_name,
        ac_parent.owner,
        ac_child.owner,
        r.level_no + 1
    FROM all_constraints ac_child
    JOIN all_cons_columns acc_child
      ON ac_child.constraint_name = acc_child.constraint_name
     AND ac_child.owner = acc_child.owner
    JOIN all_constraints ac_parent
      ON ac_child.r_constraint_name = ac_parent.constraint_name
     AND ac_child.r_owner = ac_parent.owner
    JOIN all_cons_columns acc_parent
      ON ac_parent.constraint_name = acc_parent.constraint_name
     AND ac_parent.owner = acc_parent.owner
     AND acc_parent.position = acc_child.position
    JOIN recursive_fks r
      ON ac_parent.table_name = r.child_table
     AND ac_parent.owner = r.child_owner
    WHERE ac_child.constraint_type = 'R'
)
SELECT DISTINCT
       parent_table,
       child_table,
       child_fk_column,
       parent_pk_column,
       fk_constraint_name,
       pk_constraint_name,
       parent_owner,
       child_owner,
       level_no
FROM recursive_fks
ORDER BY level_no, parent_table, child_table, child_fk_column;



PARENT_TABLE              CHILD_TABLE               CHILD_FK_COLUMN           PARENT_PK_COLUMN          FK_CONSTRAINT_NAME             PK_CONSTRAINT_NAME         PARENT_OWNER    CHILD_OWNER     LEVEL_NO
------------------------- ------------------------- ------------------------- ------------------------- ------------------------------ ------------------------------ --------------- --------------- --------
DEPT                      EMP                       DEPTNO                    DEPTNO                    FK_DEPTNO                      PK_DEPT                    ANUJ             ANUJ                   0






define O='ANUJ1'
--define T='DEPT'
define T='EMP'
set linesize 300
col XCOLUMNS for a20
col R_COLUMNS for a20
col type for a8
col TABLE_NAME for a15
col R_OWNER for a15
col R_TABLE_NAME  for a15
select	rcon.owner as r_owner, rcon.constraint_name as r_constraint_name, rcon.table_name as r_table_name, 
			listagg (rcol.column_name, ', ') WITHIN GROUP (ORDER BY rcol.owner, rcol.table_name, rcol.constraint_name) R_COLUMNS,
			rcon.constraint_type as type,	con.owner, con.table_name, con.constraint_name,  
			listagg (col.column_name, ', ') WITHIN GROUP (ORDER BY col.owner, col.table_name, col.constraint_name) XCOLUMNS
		from 	all_constraints rcon
			join all_cons_columns rcol	on rcol.owner=rcon.owner and rcol.table_name=rcon.table_name and rcol.constraint_name=rcon.constraint_name	
			left join all_constraints con 	on rcon.owner = con.r_owner and rcon.constraint_name = con.r_constraint_name
			left join all_cons_columns col	on col.owner=con.owner and col.table_name=con.table_name and col.constraint_name=con.constraint_name
			and rcol.position = col.position
		where rcon.owner = upper('&O') 
and rcon.table_name = upper('&T') 
--and rcon.constraint_type in ('P','U') 
			--and rcon.constraint_name = nvl(upper(p_constraint),rcon.constraint_name) 
--and rcon.status = 'ENABLED'
		group by rcon.owner, rcon.constraint_name, rcon.table_name, rcon.constraint_type,con.owner, con.table_name, con.constraint_name
		order by rcon.owner, rcon.constraint_name, rcon.constraint_type;


R_OWNER         R_CONSTRAINT_NAME    R_TABLE_NAME    R_COLUMNS            TYPE     OWNER           TABLE_NAME      CONSTRAINT_NAME                XCOLUMNS
--------------- -------------------- --------------- -------------------- -------- --------------- --------------- ------------------------------ --------------------
ANUJ1           PK_DEPT              DEPT            DEPTNO               P        ANUJ1           EMP             FK_DEPTNO                      DEPTNO

1 row selected.


=====

define O='ANUJ1'
--define T='DEPT'
define T='EMP'



R_OWNER         R_CONSTRAINT_NAME    R_TABLE_NAME    R_COLUMNS            TYPE     OWNER           TABLE_NAME      CONSTRAINT_NAME                XCOLUMNS
--------------- -------------------- --------------- -------------------- -------- --------------- --------------- ------------------------------ --------------------
ANUJ1           FK_DEPTNO            EMP             DEPTNO               R
ANUJ1           PK_EMP               EMP             EMPNO                P

2 rows selected.






SET LINESIZE 200  PAGESIZE 200 LONG 100000
SET TRIMOUT ON TRIMSPOOL ON
COLUMN fk_script FORMAT A120 WORD_WRAP
col t1_owner for a12
col t2_owner for a12
select fk_script from (
select fk_script,t1_owner,t2_owner from (
SELECT DISTINCT
       'ALTER TABLE ' || t1.t1_owner || '.' || t1.t1_table_name ||
       ' ADD CONSTRAINT ' || t1.t1_constraint_name ||
       ' FOREIGN KEY (' || t1.t1_column_names || ')' ||
       ' REFERENCES ' || t2.t2_owner || '.' || t2.t2_table_name ||
       '(' || t2.t2_column_names || ');' AS fk_script,t1.t1_owner,t2.t2_owner
FROM (
        SELECT a.owner AS t1_owner,
               a.table_name AS t1_table_name,
               a.constraint_name AS t1_constraint_name,
               b.r_constraint_name AS t2_constraint_name,
               LISTAGG(a.column_name, ', ')
                   WITHIN GROUP (ORDER BY a.position) AS t1_column_names
          FROM dba_cons_columns a
               JOIN dba_constraints b
                 ON a.constraint_name = b.constraint_name
                AND a.owner = b.owner
         WHERE 1=1
-- b.constraint_type = 'R'
--AND a.owner='ANUJ1'
--and a.table_name='DEPT'
      GROUP BY a.owner, a.table_name, a.constraint_name, b.r_constraint_name
     ) t1
     JOIN (
        SELECT a.owner AS t2_owner,
               a.constraint_name AS t2_constraint_name,
               a.table_name AS t2_table_name,
               LISTAGG(a.column_name, ', ')
                   WITHIN GROUP (ORDER BY a.position) AS t2_column_names
          FROM dba_cons_columns a
               JOIN dba_constraints b
                 ON a.constraint_name = b.constraint_name
                AND a.owner = b.owner
         WHERE 1=1
--b.constraint_type IN ('P', 'U')
--AND a.owner='ANUJ1'
--and a.table_name='DEPT'
      GROUP BY a.owner, a.table_name, a.constraint_name
     ) t2
       ON t1.t2_constraint_name = t2.t2_constraint_name
where 1=1
--and t1.t1_owner='ANUJ1'
--and t2.t2_table_name=t1.t1_table_name
--and t1.t1_owner=t2.t2_owner
--ORDER BY t1.t1_owner, t1.t1_table_name
)
where 1=1
and t1_owner='ANUJ1'
and t2_owner='ANUJ1'
)
;


FK_SCRIPT
------------------------------------------------------------------------------------------------------------------------
ALTER TABLE ANUJ1.EMP ADD CONSTRAINT FK_DEPTNO FOREIGN KEY (DEPTNO) REFERENCES ANUJ1.DEPT(DEPTNO);
ALTER TABLE ANUJ1.EMP1 ADD CONSTRAINT FK_DEPTNO1 FOREIGN KEY (DEPTNO) REFERENCES ANUJ1.DEPT(DEPTNO);





Disable Constraints:

SET SERVEROUTPUT ON
DECLARE
 CURSOR cur_const_disable_1 IS
 SELECT 'alter table ' || owner || '.' || table_name || ' disable constraint ' || constraint_name || ' ' text
 FROM dba_constraints
 WHERE owner IN ('ANUJ1')
 AND constraint_type IN ('R');
 
 disable_1 cur_const_disable_1%rowtype;
 
 CURSOR cur_const_disable_2 IS
 SELECT 'alter table ' || cons.owner || '.' ||cons.table_name || ' disable constraint ' || constraint_name || ' ' text
 FROM dba_constraints cons, dba_tables tabs
 WHERE cons.owner=tabs.owner
 AND cons.table_name=tabs.table_name
 AND iot_type is null
 AND cons.owner IN ('ANUJ1')
 AND constraint_type IN ('P','U');
 
 disable_2 cur_const_disable_2%rowtype;
 
BEGIN
 dbms_output.put_line(sysdate || ':Disabling constraints R');
 
 FOR disable_1 IN cur_const_disable_1 LOOP
 dbms_output.put_line(disable_1.text);
 --EXECUTE IMMEDIATE disable_1.text;
 END LOOP;
 
 dbms_output.put_line(sysdate || ':Disabling constraints P,U');
 
 FOR disable_2 IN cur_const_disable_2 LOOP
 dbms_output.put_line(disable_2.text);
-- EXECUTE IMMEDIATE disable_2.text;
 END LOOP;
END;
/


14-NOV-25:Disabling constraints R
alter table ANUJ1.EMP disable constraint FK_DEPTNO
alter table ANUJ1.EMP1 disable constraint FK_DEPTNO1
14-NOV-25:Disabling constraints P,U
alter table ANUJ1.DEPT disable constraint PK_DEPT
alter table ANUJ1.EMP1 disable constraint PK_EMP1
alter table ANUJ1.EMP disable constraint PK_EMP

PL/SQL procedure successfully completed.




-- Enable Constraints --novalidate

SET SERVEROUTPUT ON
 
DECLARE
CURSOR cur_const_enable_1 IS
SELECT 'alter table ' || owner || '.' || table_name || ' enable novalidate constraint ' || constraint_name || ' ' text
FROM dba_constraints
WHERE owner IN ('ANUJ1')
AND constraint_type IN ('P','U');
 
enable_1 cur_const_enable_1%rowtype;
 
CURSOR cur_const_enable_2 IS
SELECT 'alter table ' || owner || '.' || table_name || ' enable novalidate constraint ' || constraint_name || ' ' text
FROM dba_constraints
WHERE owner IN ('ANUJ1')
AND constraint_type IN ('R');
 
enable_2 cur_const_enable_2%rowtype;
 
BEGIN
dbms_output.put_line(sysdate || ':Enabling constraints P,U');
 
FOR enable_1 IN cur_const_enable_1 LOOP
dbms_output.put_line(enable_1.text);
-- EXECUTE IMMEDIATE enable_1.text;
END LOOP;
 
dbms_output.put_line(sysdate || ':Enabling constraints R');
 
FOR enable_2 IN cur_const_enable_2 LOOP
dbms_output.put_line(enable_2.text);
--EXECUTE IMMEDIATE enable_2.text;
END LOOP;
END;
/



14-NOV-25:Enabling constraints P,U
alter table ANUJ1.DEPT enable novalidate constraint PK_DEPT
alter table ANUJ1.EMP1 enable novalidate constraint PK_EMP1
alter table ANUJ1.EMP enable novalidate constraint PK_EMP
14-NOV-25:Enabling constraints R
alter table ANUJ1.EMP enable novalidate constraint FK_DEPTNO
alter table ANUJ1.EMP1 enable novalidate constraint FK_DEPTNO1

PL/SQL procedure successfully completed.




SET LONG 20000 LONGCHUNKSIZE 20000 PAGESIZE 0 LINESIZE 1000 FEEDBACK OFF VERIFY OFF TRIMSPOOL ON

BEGIN
   DBMS_METADATA.set_transform_param (DBMS_METADATA.session_transform, 'SQLTERMINATOR', true);
   DBMS_METADATA.set_transform_param (DBMS_METADATA.session_transform, 'PRETTY', true);
  END;
/


define tab='DEPT'
define O='ANUJ1'

SELECT DBMS_METADATA.get_ddl ('TABLE', TABLE_name, owner)
FROM   all_tables
WHERE 1=1
and owner      = UPPER('&O')
AND    table_name = '&tab'
;
SELECT DBMS_METADATA.get_ddl ('INDEX', index_name, owner)
FROM   all_indexes
WHERE 1=1
and owner      = UPPER('&O')
AND    table_name = '&tab'
;





set linesize 300 pagesize 300
col SCHEMA_NAME for a12
col CONSTRAINT_NAME for a30
col COLUMN_NAME  for a15
col TABLE_NAME for a35
col CONSTRAINT for a30
select ctr.owner as schema_name,
       ctr.constraint_name,
       ctr.table_name,
       col.column_name,
       ctr.search_condition as constraint,
       ctr.status
from sys.all_constraints ctr
join sys.all_cons_columns col
     on ctr.owner = col.owner
     and ctr.constraint_name = col.constraint_name
     and ctr.table_name = col.table_name
where 1=1
and ctr.owner  in ('ANUJ1')
and ctr.table_name='DEPT'
--and STATUS!='ENABLED'
order by ctr.owner, ctr.table_name, ctr.constraint_name;


Check detail of Foreign Key

set linesize 300 pagesize 300
col owner for a15
col "FOREIGN KEY" for a20
col "DEPENDS ON" for a20
col P_TABLE_NAME for a15
col F_TABLE_NAME for a15


define O='ANUJ1'
define T='DEPT'
define T='EMP'
SELECT distinct cp.owner owner,cp.table_name p_table_name,cp.constraint_name "DEPENDS ON",
cf.table_name f_table_name ,cf.constraint_name "FOREIGN KEY",ccp.column_name, ccp.position
FROM all_constraints cp, all_cons_columns ccp, all_constraints cf
WHERE 1=1
AND cp.constraint_name = ccp.constraint_name
AND cf.r_constraint_name = cp.constraint_name
AND cf.r_constraint_name = ccp.constraint_name
and cp.table_name = upper('&T')
and cp.owner=upper('&O')
/



OWNER           P_TABLE_NAME    DEPENDS ON           F_TABLE_NAME    FOREIGN KEY          COLUMN_NAME            POSITION
--------------- --------------- -------------------- --------------- -------------------- -------------------- ----------
ANUJ1           DEPT            PK_DEPT              EMP2            FK_DEPTNO2           DEPTNO                        1
ANUJ1           DEPT            PK_DEPT              EMP             FK_DEPTNO            DEPTNO                        1
ANUJ1           DEPT            PK_DEPT              EMP1            FK_DEPTNO1           DEPTNO                        1





define O='ANUJ1'
define T='DEPT'
col R_CONSTRAINT_NAME for a20
col STATUS for a15
col CONSTRAINT_TYPE for a15
col TABLE_NAME for a20
SELECT  TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,R_CONSTRAINT_NAME,STATUS
     FROM    DBA_CONSTRAINTS
     WHERE   OWNER = '&O'
     AND     CONSTRAINT_TYPE='R'
     AND     R_CONSTRAINT_NAME IN (SELECT CONSTRAINT_NAME FROM DBA_CONSTRAINTS WHERE TABLE_NAME='&T')
union 
SELECT  TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,R_CONSTRAINT_NAME,STATUS
     FROM    DBA_CONSTRAINTS
     WHERE   OWNER = '&O'
     --AND     CONSTRAINT_TYPE='R'
     AND     CONSTRAINT_NAME IN (SELECT CONSTRAINT_NAME FROM DBA_CONSTRAINTS WHERE TABLE_NAME='&T')

;


TABLE_NAME           CONSTRAINT_NAME                CONSTRAINT_TYPE R_CONSTRAINT_NAME    STATUS
-------------------- ------------------------------ --------------- -------------------- ---------------
DEPT                 PK_DEPT                        P                                    ENABLED
EMP                  FK_DEPTNO                      R               PK_DEPT              ENABLED

2 rows selected.




set PAGESIZE 80

SET LONG 10000 LONGCHUNKSIZE 10000 PAGESIZE 0 LINESIZE 1000 FEEDBACK OFF VERIFY OFF TRIMSPOOL ON
BEGIN
   DBMS_METADATA.set_transform_param (DBMS_METADATA.session_transform, 'SQLTERMINATOR', true);
   DBMS_METADATA.set_transform_param (DBMS_METADATA.session_transform, 'PRETTY', true);
END;
/

SELECT DBMS_METADATA.get_ddl ('TABLE', table_name, owner)
FROM   all_tables
WHERE 1=1   
and owner      = '&O'
AND    table_name in (
SELECT 
--owner , 
table_name
--, constraint_name, constraint_type, r_owner, r_constraint_name,SEARCH_CONDITION
FROM all_constraints
WHERE owner='&O'
AND constraint_name='&C'
union all
SELECT 
--owner , 
table_name
--, constraint_name, constraint_type, r_owner, r_constraint_name,SEARCH_CONDITION
FROM all_constraints
WHERE owner='&O'
AND constraint_name in ( select r_constraint_name FROM all_constraints 
                         where owner='&O'
                        AND constraint_name='&C'
                       )
--order by constraint_type
)





set linesize 300 pagesize 300
col OWNER   	for a15        
col TABLE_NAME   	for a27   
col constraint_type 	for a15
col CONSTRAINT_NAME   for a24 
col POSITION  	for 999
col R_OWNER       	for a15   
col R_TABLE_NAME   	for a20  
col R_COLUMN_NAME 	for a25
col COLUMN_NAME 	for a27

select distinct owner
               ,table_name
               ,constraint_type
               ,constraint_name
               ,position
               ,column_name
               ,r_owner
               ,r_table_name
               ,r_column_name
  from (select uc.owner
              ,uc.table_name
              ,uc.constraint_name
              ,cols.column_name
              ,cols_r.owner       as r_owner
              ,cols_r.table_name  as r_table_name
              ,cols_r.column_name as r_column_name
              ,cols.position
              ,uc.constraint_type
          from dba_constraints uc
          join dba_cons_columns cols on cols.constraint_name = uc.constraint_name
          left join dba_cons_columns cols_r on cols_r.constraint_name = uc.r_constraint_name
         where uc.constraint_type not in ('C', 'U') 
          -- C = check constraint, P = primary key, R = Foreign key, U = unique key
           and uc.table_name not like 'BIN$%' -- exclude system "tables"
           -- # set your filters here
           and uc.owner = 'ANUJ1'
           and cols_r.owner='ANUJ1'
        )
-- # and set the rest of your filters here
-- start with table_name  = 'EMP'
--        and column_name = 'EMPNO'
connect by nocycle prior owner = r_owner
       and prior table_name = r_table_name
       and prior column_name = r_column_name
 order by owner
         ,table_name
         ,constraint_type
         ,constraint_name
         ,position
/





OWNER           TABLE_NAME                  CONSTRAINT_TYPE CONSTRAINT_NAME          POSITION COLUMN_NAME                 R_OWNER         R_TABLE_NAME         R_COLUMN_NAME
--------------- --------------------------- --------------- ------------------------ -------- --------------------------- --------------- -------------------- -------------------------
ANUJ1           EMP                         R               FK_DEPTNO                       1 DEPTNO                      ANUJ1           DEPT                 DEPTNO
ANUJ1           T_INVOICE_ITEM              R               FK_INVITEM_INVOICE              1 INVOICE_ID                  ANUJ1           T_INVOICE            INVOICE_ID
ANUJ1           T_INVOICE_ITEM              R               FK_INVITEM_PRODUCT              1 PRODUCT_ID                  ANUJ1           T_PRODUCT            PRODUCT_ID
ANUJ1           T_INVOICE_ITEM_DELIVERY     R               FK_INVITDEL                     1 INVOICE_ID                  ANUJ1           T_INVOICE_ITEM       INVOICE_ID
ANUJ1           T_INVOICE_ITEM_DELIVERY     R               FK_INVITDEL                     1 INVOICE_ID                  ANUJ1           T_INVOICE_ITEM       PRODUCT_ID
ANUJ1           T_INVOICE_ITEM_DELIVERY     R               FK_INVITDEL                     2 PRODUCT_ID                  ANUJ1           T_INVOICE_ITEM       INVOICE_ID
ANUJ1           T_INVOICE_ITEM_DELIVERY     R               FK_INVITDEL                     2 PRODUCT_ID                  ANUJ1           T_INVOICE_ITEM       PRODUCT_ID
ANUJ1           T_PRODUCT                   R               FK_PROD_PROD                    1 PRODUCT_EQUIVALENT          ANUJ1           T_PRODUCT            PRODUCT_ID
ANUJ1           T_PRODUCT                   R               FK_PROD_PROV                    1 PROVIDER_ID                 ANUJ1           T_PROVIDER           PROVIDER_ID
ANUJ1           T_PRODUCT_WAREHOUSE         R               FK_PRODWARE_PRODUCT             1 PRODUCT_ID                  ANUJ1           T_PRODUCT            PRODUCT_ID
ANUJ1           T_PRODUCT_WAREHOUSE         R               FK_PRODWARE_WAREHOUSE           1 WAREHOUSE_ID                ANUJ1           T_WAREHOUSE          WAREHOUSE_ID

11 rows selected.


======================================

set linesize 300 pagesize 300
col FK_COLUMNS for a25
col PK_COLUMNS for a25
col PARENT_TABLE for a25
col CHILD_TABLE  for a30       
col FK_CONSTRAINT for a30
col FK_STATUS for a15
col PK_STATUS for a15

WITH fk_raw AS (
    SELECT
        fk_constraint,
        parent_table,
        child_table,
        LISTAGG(fk_col, ',') WITHIN GROUP (ORDER BY col_position) AS fk_columns,
        LISTAGG(pk_col, ',') WITHIN GROUP (ORDER BY col_position) AS pk_columns,
        fk_status,
        pk_status
    FROM (
        SELECT
            ac_child.constraint_name AS fk_constraint,
            ac_parent.table_name AS parent_table,
            ac_child.table_name AS child_table,
            acc_child.column_name AS fk_col,
            acc_parent.column_name AS pk_col,
            acc_child.position AS col_position,
            ac_child.status AS fk_status,
            ac_parent.status AS pk_status,
            ROW_NUMBER() OVER (
                PARTITION BY ac_child.constraint_name, acc_child.column_name, acc_parent.column_name
                ORDER BY acc_child.position
            ) AS rn
        FROM all_constraints ac_child
        JOIN all_constraints ac_parent
            ON ac_child.r_constraint_name = ac_parent.constraint_name
           AND ac_child.r_owner = ac_parent.owner
        JOIN all_cons_columns acc_child
            ON ac_child.constraint_name = acc_child.constraint_name
           AND ac_child.owner = acc_child.owner
        JOIN all_cons_columns acc_parent
            ON ac_parent.constraint_name = acc_parent.constraint_name
           AND acc_parent.owner = ac_parent.owner
           AND acc_parent.position = acc_child.position
        WHERE ac_child.constraint_type = 'R'
          AND ac_parent.owner = UPPER('ANUJ1')
    ) t
    WHERE rn = 1
    GROUP BY fk_constraint, parent_table, child_table, fk_status, pk_status
)
SELECT PARENT_TABLE , PK_STATUS,CHILD_TABLE,FK_STATUS,fk_CONSTRAINT , PK_COLUMNS,FK_COLUMNS
FROM fk_raw
where 1=1
--and FK_STATUS!='ENABLED'
--and PARENT_TABLE not like 'XX%'
ORDER BY parent_table, child_table, fk_constraint;
















from web !!!!

CREATE OR REPLACE TYPE STRINGARRAY AS TABLE OF VARCHAR2(50);

CREATE OR REPLACE FUNCTION get_child_tables (
   ptable   VARCHAR2,
   powner   VARCHAR2 DEFAULT 'ANUJ1',
   plevel   NUMBER   DEFAULT 10
) RETURN stringarray PIPELINED
AS
   atname       stringarray := stringarray();
   vlevel       NUMBER;
   vtname       VARCHAR2(50);
   nindex       NUMBER := 0;
   bprocessed   BOOLEAN := FALSE;

   CURSOR c1 (powner_in VARCHAR2, ptable_in VARCHAR2, plevel_in NUMBER)
   IS
      SELECT LEVEL,
             LPAD(' ', (LEVEL - 1) * 4, ' ') || pt AS tname
      FROM (
         SELECT a.owner w1, a.table_name pt, a.constraint_name c1,
                a.r_constraint_name r1,
                b.owner w2, b.table_name ct, b.constraint_name c2, b.r_constraint_name r2
           FROM all_constraints a
           LEFT JOIN all_constraints b
             ON a.constraint_name = b.r_constraint_name
            AND a.owner = b.owner
          WHERE a.owner = UPPER(powner_in)
            AND a.constraint_type IN ('P','R')
      )
      START WITH pt = UPPER(ptable_in)
      CONNECT BY PRIOR ct = pt AND LEVEL <= plevel_in;
BEGIN
   atname.EXTEND;
   atname(1) := 'NOTHING';

   OPEN c1(powner, ptable, plevel);

   LOOP
      FETCH c1 INTO vlevel, vtname;
      EXIT WHEN c1%NOTFOUND;

      bprocessed := FALSE;

      IF nindex > 1 AND atname(atname.LAST - 1) = vtname THEN
         bprocessed := TRUE;
      END IF;

      IF NOT bprocessed THEN
         nindex := nindex + 1;
         atname.EXTEND;
         atname(nindex) := vtname;

         PIPE ROW (vlevel || ' => ' || vtname);
      END IF;

   END LOOP;

   CLOSE c1;

   RETURN;
EXCEPTION
   WHEN OTHERS THEN
      DBMS_OUTPUT.put_line(SQLERRM);
      RETURN;
END get_child_tables;
/



SELECT * FROM TABLE(get_child_tables('DEPT'));
SELECT * FROM TABLE( get_child_tables('DEPT','ANUJ1',3));
SELECT * FROM TABLE(get_child_tables('DEPT'));

COLUMN_VALUE
--------------------------------------------------
1 => DEPT
2 =>     EMP

SQL> SELECT * FROM TABLE(get_child_tables('EMP'));

COLUMN_VALUE
--------------------------------------------------
1 => EMP
1 => EMP

SQL> SELECT * FROM TABLE( get_child_tables('DEPT','ANUJ1',3));

COLUMN_VALUE
--------------------------------------------------
1 => DEPT
2 =>     EMP


SELECT * FROM TABLE( get_child_tables('DEPT','ANUJ1',5));


====



CREATE OR REPLACE TYPE STRINGARRAY AS TABLE OF VARCHAR2(50);


CREATE OR REPLACE FUNCTION anuj1.get_child_tables (
   ptable   VARCHAR2,
   powner   VARCHAR2 DEFAULT 'ANUJ1',
   plevel   NUMBER DEFAULT 10
)
   RETURN stringarray
   PIPELINED
IS
   atname       stringarray   := stringarray ();
   vlevel       NUMBER;
   vtname       VARCHAR2 (50);
   nindex       NUMBER        := 0;
   bprocessed   BOOLEAN       := FALSE;

   CURSOR c1 (powner_in IN VARCHAR2, ptable_in VARCHAR2, plevel_in NUMBER)
   IS
      SELECT LEVEL,
             LPAD (' ', (LEVEL - 1) * 4, ' ') || pt AS tname
        FROM (
             SELECT a.owner w1,
                    a.table_name pt,
                    a.constraint_name c1,
                    a.r_constraint_name r1,
                    b.owner w2,
                    b.table_name ct,
                    b.constraint_name c2,
                    b.r_constraint_name r2
               FROM all_constraints a
               LEFT JOIN all_constraints b
                 ON a.constraint_name = b.r_constraint_name
                AND a.owner = b.owner
              WHERE a.owner = UPPER (powner_in)
                AND a.constraint_type IN ('P','R')
             )
      START WITH pt = UPPER(ptable_in)
      CONNECT BY PRIOR ct = pt
      AND LEVEL <= plevel_in;
BEGIN
   -- first element
   atname.EXTEND;
   atname(1) := 'NOTHING';

   OPEN c1 (powner, ptable, plevel);

   LOOP
      FETCH c1 INTO vlevel, vtname;
      EXIT WHEN c1%NOTFOUND;

      bprocessed := FALSE;

      IF nindex > 1
         AND atname(atname.LAST - 1) = vtname
      THEN
         bprocessed := TRUE;
      END IF;

      IF NOT bprocessed
      THEN
         nindex := nindex + 1;
         atname.EXTEND;
         atname(nindex) := vtname;

         PIPE ROW (vlevel || ' => ' || vtname);
      END IF;

   END LOOP;

   CLOSE c1;

   RETURN;

EXCEPTION
   WHEN OTHERS THEN
      DBMS_OUTPUT.put_line(SQLERRM);
      RETURN;
END get_child_tables;
/



SELECT * FROM TABLE(anuj1.get_child_tables('DEPT', 'ANUJ1', 6));


SELECT * FROM TABLE(anuj1.get_child_tables('DEPT', 'ANUJ1', 6));


COLUMN_VALUE
--------------------------------------------------
1 => DEPT
2 =>     EMP



***************************





SET SERVEROUTPUT ON SIZE 1000000
DECLARE
    v_root_table  VARCHAR2(200) := 'DEPT';   -- root table
    v_deptno      NUMBER := 10;              -- deptno filter
    v_count       PLS_INTEGER := 0;
    v_user        VARCHAR2(200) := 'SCOTT';
    v_sql         CLOB;
    v_rows        NUMBER := 0;
    v_batch_size  NUMBER := 1000;            -- rows per batch
BEGIN
    DBMS_OUTPUT.PUT_LINE('--- BATCH FK-SAFE DELETE START for ' || v_user || ' ---');
    DBMS_OUTPUT.PUT_LINE('Root table: ' || v_root_table || '  DEPTNO = ' || v_deptno);
    DBMS_OUTPUT.PUT_LINE('');

    FOR rec IN (
        WITH RECURSIVE_TREE(child_table, parent_table, child_fk_column, parent_pk_column, lvl) AS (
            -- anchor: direct children of the root
            SELECT cc.table_name,
                   p.table_name,
                   cc.column_name,
                   pc.column_name,
                   1
            FROM all_constraints p
            JOIN all_cons_columns pc
              ON pc.constraint_name = p.constraint_name AND pc.owner = p.owner
            JOIN all_constraints fk
              ON fk.r_constraint_name = p.constraint_name AND fk.owner = p.owner
            JOIN all_cons_columns cc
              ON cc.constraint_name = fk.constraint_name AND cc.owner = fk.owner
            WHERE p.table_name = v_root_table
              AND p.owner = v_user
              AND fk.constraint_type = 'R'
            UNION ALL
            -- recursive: find children of previously found child tables
            SELECT cc.table_name,
                   fk_parent.table_name,
                   cc.column_name,
                   pc.column_name,
                   rt.lvl + 1
            FROM RECURSIVE_TREE rt
            JOIN all_constraints fk_parent
              ON fk_parent.table_name = rt.child_table AND fk_parent.owner = v_user
            JOIN all_constraints fk
              ON fk.r_constraint_name = fk_parent.constraint_name AND fk.owner = v_user
            JOIN all_cons_columns cc
              ON cc.constraint_name = fk.constraint_name AND cc.owner = fk.owner
            JOIN all_constraints pk
              ON pk.constraint_name = fk.r_constraint_name AND pk.owner = v_user
            JOIN all_cons_columns pc
              ON pc.constraint_name = pk.constraint_name AND pc.owner = pk.owner
            WHERE fk.constraint_type = 'R'
        )
        SELECT DISTINCT child_table, parent_table, child_fk_column, parent_pk_column, lvl
        FROM RECURSIVE_TREE
        ORDER BY lvl DESC, child_table
    ) LOOP
        v_count := v_count + 1;
        DBMS_OUTPUT.PUT_LINE('Processing table: ' || rec.child_table);

        LOOP
            v_sql := 'DELETE FROM ' || v_user || '.' || rec.child_table || ' WHERE ' ||
                     rec.child_fk_column || ' IN (SELECT ' || rec.parent_pk_column ||
                     ' FROM ' || v_user || '.' || rec.parent_table || ' WHERE DEPTNO = :deptno) AND ROWNUM <= :batch_size';

            EXECUTE IMMEDIATE v_sql USING v_deptno, v_batch_size;
            v_rows := SQL%ROWCOUNT;

            EXIT WHEN v_rows = 0;

            DBMS_OUTPUT.PUT_LINE('  Deleted ' || v_rows || ' rows from ' || rec.child_table);
            COMMIT;
        END LOOP;
    END LOOP;

    -- Delete from root table in batches
    DBMS_OUTPUT.PUT_LINE('Processing root table: ' || v_root_table);
    LOOP
        v_sql := 'DELETE FROM ' || v_user || '.' || v_root_table || 
                 ' WHERE DEPTNO = :deptno AND ROWNUM <= :batch_size';
        EXECUTE IMMEDIATE v_sql USING v_deptno, v_batch_size;
        v_rows := SQL%ROWCOUNT;

        EXIT WHEN v_rows = 0;

        DBMS_OUTPUT.PUT_LINE('  Deleted ' || v_rows || ' rows from ' || v_root_table);
        COMMIT;
    END LOOP;

    DBMS_OUTPUT.PUT_LINE('--- BATCH FK-SAFE DELETE COMPLETE ---');
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('ERROR: ' || SQLERRM);
        ROLLBACK;
        RAISE;
END;
/


***********************



SET SERVEROUTPUT ON SIZE 1000000
DECLARE
    -- Collection types
    TYPE t_col_list IS TABLE OF VARCHAR2(100);
    TYPE t_val_list IS TABLE OF VARCHAR2(4000);

    v_user         VARCHAR2(200) := 'SCOTT';         -- Schema
    v_root_table   VARCHAR2(200) := 'DEPT';          -- Root table
    v_batch_size   NUMBER := 1000;

    -- Root table filters
    v_filter_cols  t_col_list := t_col_list('DEPTNO');
    v_filter_vals  t_val_list := t_val_list('10');
    v_where_clause VARCHAR2(1000);

    v_script CLOB;
    v_line   VARCHAR2(4000);
BEGIN
    -- Build WHERE clause only for columns that exist
    v_where_clause := '';
    FOR i IN 1..v_filter_cols.COUNT LOOP
        DECLARE
            v_cnt NUMBER;
        BEGIN
            SELECT COUNT(*)
            INTO v_cnt
            FROM all_tab_columns
            WHERE owner = v_user
              AND table_name = v_root_table
              AND column_name = v_filter_cols(i);

            IF v_cnt > 0 THEN
                IF v_where_clause IS NOT NULL AND v_where_clause <> '' THEN
                    v_where_clause := v_where_clause || ' AND ';
                END IF;
                v_where_clause := v_where_clause || v_filter_cols(i) || ' = ' || CHR(39) || v_filter_vals(i) || CHR(39);
            END IF;
        END;
    END LOOP;

    DBMS_OUTPUT.PUT_LINE('--- PRINT-ONLY FK-SAFE DELETE SCRIPT ---');
    DBMS_OUTPUT.PUT_LINE('Schema: ' || v_user || '  Root: ' || v_root_table);
    DBMS_OUTPUT.PUT_LINE('Root filter: ' || v_where_clause);
    DBMS_OUTPUT.PUT_LINE('');

    -- Traverse FK tree and print delete statements
    FOR rec IN (
        WITH RECURSIVE_TREE(child_table, parent_table, child_fk_column, parent_pk_column, lvl) AS (
            SELECT cc.table_name,
                   p.table_name,
                   cc.column_name,
                   pc.column_name,
                   1
            FROM all_constraints p
            JOIN all_cons_columns pc
              ON pc.constraint_name = p.constraint_name AND pc.owner = p.owner
            JOIN all_constraints fk
              ON fk.r_constraint_name = p.constraint_name AND fk.owner = p.owner
            JOIN all_cons_columns cc
              ON cc.constraint_name = fk.constraint_name AND cc.owner = fk.owner
            WHERE p.table_name = v_root_table
              AND p.owner = v_user
              AND fk.constraint_type = 'R'
            UNION ALL
            SELECT cc.table_name,
                   fk_parent.table_name,
                   cc.column_name,
                   pc.column_name,
                   rt.lvl + 1
            FROM RECURSIVE_TREE rt
            JOIN all_constraints fk_parent
              ON fk_parent.table_name = rt.child_table AND fk_parent.owner = v_user
            JOIN all_constraints fk
              ON fk.r_constraint_name = fk_parent.constraint_name AND fk.owner = v_user
            JOIN all_cons_columns cc
              ON cc.constraint_name = fk.constraint_name AND cc.owner = fk.owner
            JOIN all_constraints pk
              ON pk.constraint_name = fk.r_constraint_name AND pk.owner = v_user
            JOIN all_cons_columns pc
              ON pc.constraint_name = pk.constraint_name AND pc.owner = pk.owner
            WHERE fk.constraint_type = 'R'
        )
        SELECT DISTINCT child_table, parent_table, child_fk_column, parent_pk_column, lvl
        FROM RECURSIVE_TREE
        ORDER BY lvl DESC, child_table
    ) LOOP
        DBMS_OUTPUT.PUT_LINE('-- Child table: ' || rec.child_table);

        v_line :=
            'DELETE FROM ' || v_user || '.' || rec.child_table || CHR(10) ||
            ' WHERE ' || rec.child_fk_column || ' IN (' || CHR(10) ||
            '     SELECT ' || rec.parent_pk_column || CHR(10) ||
            '     FROM ' || v_user || '.' || rec.parent_table || CHR(10) ||
            '     WHERE ' || v_where_clause || CHR(10) ||
            ' );' || CHR(10);

        DBMS_OUTPUT.PUT_LINE(v_line);
    END LOOP;

    -- Root table delete
    DBMS_OUTPUT.PUT_LINE('-- Root table delete');
    v_line :=
        'DELETE FROM ' || v_user || '.' || v_root_table || CHR(10) ||
        ' WHERE ' || v_where_clause || ';' || CHR(10);

    DBMS_OUTPUT.PUT_LINE(v_line);

    DBMS_OUTPUT.PUT_LINE('--- PRINT COMPLETE ---');

END;
/

                 
				 

--- PRINT-ONLY FK-SAFE DELETE SCRIPT ---
Schema: SCOTT  Root: DEPT
Root filter: DEPTNO = '10'
-- Child table: EMP
DELETE FROM SCOTT.EMP
 WHERE DEPTNO IN (
     SELECT DEPTNO
     FROM SCOTT.DEPT
     WHERE DEPTNO = '10'
 );

-- Root table delete
DELETE FROM SCOTT.DEPT
 WHERE DEPTNO = '10';

--- PRINT COMPLETE ---

PL/SQL procedure successfully completed.





================


https://anuj-singh.blogspot.com/2025/    Delete Foreign Keys and Primary Table Rows

1 comment:

Anuj Singh said...

Oracle missing index on foreign key

http://anuj-singh.blogspot.com/2011/09/oracle-missing-index-on-foreign-key.html

Oracle DBA

anuj blog Archive