Question

We have two tables:

HUSBANDS
---------------
id
name
surname
age

WIFES
---------------
id
name
surname
age
husbandId                      --(with constrain -> HUSBANDS.ID)

and suppose, that we need to write procedure removing wifes older than 60 years together with their husbands ;)

It could be perfect to do this using typical SQL statement, but it is impossible in Oracle to delete rows from two tables in one DELETE statement, right? So...

We can't do this like this:

PROCEDURE remove_old_wifes() IS
BEGIN
    DELETE FROM husbands WHERE id IN (SELECT husbandId FROM wifes WHERE age >= 60); 
    DELETE FROM wifes WHERE age >= 60; 
END;

because of constrain.

On the other hand, undermentioned solution is wrong as well:

PROCEDURE remove_old_wifes() IS
BEGIN
    DELETE FROM wifes WHERE age >= 60; 
    DELETE FROM husbands WHERE id IN (SELECT husbandId FROM wifes WHERE age >= 60); 
END;

bacause when we remove the wifes firstly, none of the husbands will be removed...

What is typical solution of this case?

IMPORTANT: I can't set cascade.

Was it helpful?

Solution

You can update the husbands first with an indicator that they have no wife. For your data, let's use age = -1. Then delete from wifes [sic] and then delete from husbands.

update husbands
    set age = -1
    where id in (select husbandId from wifes where age >= 60);

delete from wifes where age >= 60;

delete from husbands where age = -1;

OTHER TIPS

If no "unmarried husbands" are allowed in the table, you could just first remove the wives, and then all husbands that no longer have a wife. If temporary inconsistency is a problem, you may want to wrap the deletes inside a transaction.

PROCEDURE remove_old_wifes() IS
BEGIN
    DELETE FROM wifes WHERE age >= 60; 
    DELETE FROM husbands WHERE id NOT IN (SELECT husbandId FROM wifes); 
END;

You have many clause of foreign keys in Oracle. For example you can have the "on delete cascade" clause in you foreign key:

alter table WIFES 
add foreign key (husbandId ) 
   references HUSBANDS(id)
on delete cascade;

with this clause, you could delete rows of two table with only one delete. So your procedure will be:

PROCEDURE remove_old_wifes() IS
BEGIN
    DELETE FROM husbands WHERE id IN (SELECT husbandId FROM wifes WHERE age >= 60); 
END;

If it's impossible for you to set the on delete cascade clause, you should use global temporary tables for example:

create table gtt_id( id number) on commit delete rows;


PROCEDURE remove_old_wifes() IS
BEGIN
    insert into gtt_id SELECT husbandId FROM wifes WHERE age >= 60;
    delete FROM wifes WHERE age >= 60
    DELETE FROM husbands WHERE id IN (SELECT id FROM gtt_id); 
END;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top