I'm trying to enforce a restriction of a many-to-many relation with total participation on one of the sides using SQL in an Oracle database but can't figure out how.
For example, I have a set of tables that can be described by this entity-relationship diagram (or the ASCII version below):
( id1 )---[ E1 ] ====== < R > ------ [ E2 ]---( id2 )
Where the entities E1 have a relation R to the entities E2, and every entry in E1 has to be related to at least one entry of E2.
This translates to the tables E1(id1), R(id1, id2), and E2(id2), and I want to make sure that at any given point, every value id1 in E1, also appears as id1 in R at least once.
I've successfully managed to enforce this rule during insertions of new E1 entries by making the FOREIGN KEY id1 REFERENCES E1(id1)
constraint on R be DEFERRABLE
, creating a trigger BEFORE INSERT ON E1
that fails if :new.id1
doesn't exist in R, then always inserting a new entry with id1 = x in R before adding a new entry with id1 = x in E1.
However, I can't find a way to enforce this restriction upon deletion of an entry in R, as triggers wouldn't be able to check for the existence of another entry with the id1 of the removed entry in R since the table is mutating.
This is the SQL trigger definition I tried to use but fails because "table tiposDoRestaurante is mutating":
create or replace trigger trig_E1StillHasAnE2 after delete on R
for each row
declare numRelated int;
begin
select count(id1) into numRelated
from R
where id1 = :old.id1
group by id1;
if numRelated = 0 then
Raise_Application_Error(-20011, 'Deletion of the only relation of an E1 to E2s');
end if;
end;
/