我试图在Oracle数据库中使用SQL在其中一方强制执行多对多关系的限制,但不知道如何操作。
例如,我有一组可以用this entity-relationship diagram(或下面的ASCII版本)描述的表:
( id1 )---[ E1 ] ====== < R > ------ [ E2 ]---( id2 )
其中实体E1与实体E2具有关系R,并且E1中的每个条目必须与E2的 * 至少一个 * 条目相关。
这可以转化为表E1(id1)、R(id1,id2)和E2(id2),我想确保在任何给定点,E1中的每个值id1在R中至少出现一次。
我已经成功地在插入新的E1条目时执行了这个规则,方法是将R上的FOREIGN KEY id1 REFERENCES E1(id1)
约束设为DEFERRABLE
,创建一个触发器BEFORE INSERT ON E1
,如果:new.id1
在R中不存在,则触发器BEFORE INSERT ON E1
失败,然后总是在R中插入一个id1 = x的新条目,然后在E1中添加一个id1 = x的新条目。
然而,我找不到一种方法在R中删除条目时强制执行此限制,因为触发器无法检查R中是否存在另一个具有已删除条目的id1的条目,因为表正在发生变化。
这是我尝试使用的SQL触发器定义,但失败了,因为“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;
/
1条答案
按热度按时间y1aodyip1#
一种可能的解决方案是使用复合触发器,该触发器允许对同一事件执行多个触发器操作。建议如下:使用BEFORE STATEMENT触发器创建一个临时表,该表包含R中至少有一个相关E2条目的所有E1条目的ID。然后使用FOR EACH ROW触发器检查删除的条目是否是临时表中与其对应的E1条目唯一相关的条目。如果是,则引发异常以阻止删除。例如: