如何为删除后写入触发器,其中包含在触发器体中同一表的另一个删除?



下面是关系模式,

college(ID int, name text, grade int);
friend(ID1 int, ID2 int);
likes(ID1 int, ID2 int);

我写了一个触发器来维持友谊关系的对称性。这意味着如果(X, Y)从友元中删除,(Y, X)也应该被删除。

下面是表的创建:

create table college
(
id    int auto_increment primary key,
name  text not null,
grade int  not null
);
create table likes
(
id1 int not null,
id2 int
);
create table friend
(
id1 int not null,
id2 int not null,
constraint friend_pk
primary key (id1, id2),
constraint friend_college_id_fk
foreign key (id1) references college (id)
constraint friend_college_id_fk2
foreign key (id2) references college (id)
);

我写了以下触发器;

delimiter //
drop trigger if exists Friend_Delete //
create trigger Friend_Delete
after delete
on friend
for each row
begin
delete
from friend
where id1 = OLD.id2
and id2 = OLD.id1;
end //
delimiter ;

但是当我执行下面的查询时,

delete from friend where id1 = 1 and id2 = 2;

它给了我这个结果;无法更新存储函数/触发器中的表'friend',因为它已经被调用该存储函数/触发器的语句使用了

我在谷歌上搜索了这个问题,它被称为无休止的递归调用。但是当我们说在删除之后,它被删除了为什么我们不能在这里执行另一个删除呢?

数据库引擎正在确保您不能编写触发永无止境的触发器序列的触发器。它不会看你代码的逻辑,它只是确保你不会触发一系列持续运行的触发动作。是否在"之后"并不重要。原删除。

一般来说,我建议在应用程序代码中处理这个问题,而不是在数据库代码中。触发器有很多问题——它们很难测试,它们很难调试,它们需要开发人员记住做一件事(在这种情况下删除一行)会有副作用(自动删除另一行),它们会产生奇怪的性能问题(触发的级联序列可能看起来像你的数据库很慢)。
delete from friend where id1 = 1 and id2 = 2;

使用上面的查询,您正在删除id1 =1和id2= 2的行

然后触发器试图删除所有id1=2和id2=1的行

也会触发Friend_Delete删除id1=1, id2=2的行这是你使用的第一个删除条件。这样递归就发生了,并且创建了一个无限循环。

最新更新