如何避免MySQL中的循环触发器依赖

6
我在使用MySQL中的触发器时遇到了一个小问题。
假设我们有两个表:
- TableA - TableB
还有两个触发器:
- TriggerA:在TableA上删除并更新TableB时触发 - TriggerB:在TableB上删除并删除TableA时触发
问题是,当我在TableB中删除某些行时,TriggerB会触发并删除TableA中的一些元素,然后TriggerA会触发并尝试更新TableB。
它失败了,因为TriggerA尝试更新正在被删除的一些行。
如何避免这种循环依赖?
这两个触发器都不是无用的,所以我不知道应该怎么做来解决这个问题。

1
你能展示一些关于相关表格的数据,并告诉我们触发器的具体作用和定义方式吗? - Brendon Dugan
@kensou:你能展示一下你的模式图以及这两个触发器的目的吗?它很可能可以被规范化以避免循环触发器(或所有触发器)。 - ypercubeᵀᴹ
1个回答

11

尝试使用变量。

第一个触发器:

CREATE TRIGGER trigger1
  BEFORE DELETE
  ON table1
  FOR EACH ROW
BEGIN
  IF @deleting IS NULL THEN
    SET @deleting = 1;
    DELETE FROM table2 WHERE id = OLD.id;
    SET @deleting = NULL;
  END IF;
END

第二个触发器:

CREATE TRIGGER trigger2
  BEFORE DELETE
  ON table2
  FOR EACH ROW
BEGIN
  IF @deleting IS NULL THEN
    SET @deleting = 1;
    DELETE FROM table1 WHERE id = OLD.id;
    SET @deleting = NULL;
  END IF;
END

并且还有在 DELETE 之后触发的其他触发器:

CREATE TRIGGER trigger3
  AFTER DELETE
  ON table1
  FOR EACH ROW
BEGIN
  SET @deleting = NULL;
END

CREATE TRIGGER trigger4
  AFTER DELETE
  ON table2
  FOR EACH ROW
BEGIN
  SET @deleting = NULL;
END

编写BEFORE DELETE触发器来删除记录,以及AFTER DELETE触发器来将@deleting变量重置为NULL可能是值得的。我已经修改了答案。 - Devart
我们为什么需要触发器3和4?在BEFORE DELETE触发器中,我们不是在删除后立即将@deleting重置为NULL吗? - Kennet Celeste
此外,您可以将deleting声明在所有触发器都可以访问的位置。 - Kennet Celeste
2
@KennetCeleste 在 MySQL 中以 @ 开头的变量是会话全局变量,因此 SET @deleting = 1; 就是定义它的命令。在定义之前执行 select @deleting 将返回 null - Brian Leishman
所以这种方法在远程服务器上行不通,对吧? - temo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接