Here is a complete example of how this can be done. However, you need flashback request privileges in the child table.
Here is the setting.
create table parent_tab (parent_id number primary key, val varchar2(20)); create table child_tab (child_id number primary key, parent_id number, child_val number, constraint child_par_fk foreign key (parent_id) references parent_tab); insert into parent_tab values (1,'Red'); insert into parent_tab values (2,'Green'); insert into parent_tab values (3,'Blue'); insert into parent_tab values (4,'Black'); insert into parent_tab values (5,'White'); insert into child_tab values (10,1,100); insert into child_tab values (20,3,100); insert into child_tab values (30,3,100); insert into child_tab values (40,4,100); insert into child_tab values (50,5,200); commit; select * from parent_tab where parent_id not in (select parent_id from child_tab);
Now remove the subset of children (with parents 1,3 and 4, but not 5).
delete from child_tab where child_val = 100;
Then, get parent_ids from the current state of COMMITTED child_tab (i.e. before they were before the deletion), and delete those that your session did NOT delete. This gives you the subset that has been deleted. Then you can remove them from parent_tab
delete from parent_tab where parent_id in (select parent_id from child_tab as of scn dbms_flashback.get_system_change_number minus select parent_id from child_tab);
Green still exists (since it still does not have an entry in the child table), and Red still exists (since it still has an entry in the child table)
select * from parent_tab where parent_id not in (select parent_id from child_tab); select * from parent_tab;
This is an exotic / unusual operation, so if I did this, I would probably be a little careful and lock the child and parent tables in exclusive mode at the start of the transaction. Also, if the child table was large, it would not be particularly efficient, so I would choose a PL / SQL solution such as Rajesh's.