This is a great exercise in developing your PL/SQL skills and general Oracle knowledge!
You need to identify all constrained columns in all tables with relations descending from your master table. You can get all the information you need from two views: ALL_CONSTRAINTS and ALL_CONS_COLUMNS. (If all the tables are in the same schema as the user executing the script, you can use USER_CONSTRAINTS and USER_CONS_COLUMNS if you prefer)
This query will find all the foreign key constraints which refer back to a given table (CUSTOMER
in this example):
SELECT constraint_name, table_name, constraint_type
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 = 'CUSTOMER');
CONSTRAINT_NAME C
------------------------------ -
CUSTOMER_FK1 R
CUSTOMER_FK4 R
CUSTOMER_FK5 R
CUSTOMER_FK3 R
CUSTOMER_FK2 R
Now, for each of the results from that query, you can use the CONSTRAINT_NAME
column to get a table and column name which you can use to write DELETE statements to delete all child rows in all child tables.
This example gets the table and column name for a constraint called CUSTOMER_FK1
SELECT table_name, column_name
FROM user_cons_columns
WHERE constraint_name = 'CUSTOMER_FK1'
TABLE_NAME COLUMN_NAME
----------------------------- ------------------------------------
RESERVATION CUSTOMER_UID
So you could do, for example:
DELETE FROM reservation
WHERE customer_uid = 00153464
or
DELETE FROM reservation
WHERE customer_uid IN (SELECT customer_uid
FROM customer
WHERE customer_type = 'X')
But your child tables also have child tables, so of course you will have to delete those child rows (call them grandchild rows) first. Supposing there is a table called reservation_detail which has a foreign key relationship with reservation, your delete command for reservation_detail might look like:
DELETE FROM reservation_detail
WHERE reservation_uid in (SELECT reservation_uid
FROM reservation
WHERE customer_uid IN (SELECT customer_uid
FROM customer
WHERE customer_type = 'X')
And if reservation_detail also has children... you get the idea. Of course you could use joins instead of nested queries, but the principle is the same: the more levels deep your dependencies go, the more complex your delete commands become.
So now you know how to do it, the challenge is to write a generic PL/SQL script to delete all child rows, grandchild rows, great-grandchild rows ... (ad infinitum) for any given table, from the bottom up. You will have to employ recursion. Should be a fun program to write!
(Last edit: removed the script; see my other answer for the final solution.)