【问题标题】:Error Code: 1442. Can't update table 'A' in trigger because it is already used by statement which invoked this trigger错误代码:1442。无法更新触发器中的表 \'A\',因为它已被调用此触发器的语句使用
【发布时间】:2023-01-12 16:54:09
【问题描述】:

我对mysql有以下问题: 我有一个带有触发器的表 A,当 A 中的某些内容发生变化时,该触发器会更新表 B 的列。这个触发器有效。

当 B 中的某些内容发生变化时,我需要更新 A 列的可能性,但第二个触发器会产生错误。 我知道是递归的,但我该怎么做呢?

exp.

    trigger A:
delimiter $$

CREATE TRIGGER TAU_A
AFTER UPDATE ON table_A FOR EACH ROW
       begin
      IF OLD.to_read <> NEW.to_read THEN
            update table_B
            set is_read=if(new.to_read=1,0,1)
            where id=new.id;
      END IF;
       
END$$

trigger B:
delimiter $$

CREATE TRIGGER TAU_B
AFTER UPDATE ON table_b FOR EACH ROW
       begin
      IF OLD.is_read <> NEW.is_readTHEN
            update table_a
            set to_read=if(new.is_read=1,0,1)
            where id=new.id;
      END IF;
       
END$$

【问题讨论】:

    标签: mysql triggers mysql-error-1442


    【解决方案1】:

    使用用户定义的变量,检查链接更新。

    演示

    @check_for_cycle 用户定义变量用于防止循环。变量名称在系统中必须是唯一的(即它必须仅在此触发器包中使用)并提供无干扰(包括可能修改这些表数据的其他应用程序)。

    CREATE TABLE t1 (id INT PRIMARY KEY, val INT);
    CREATE TABLE t2 (id INT PRIMARY KEY, val INT);
    INSERT INTO t1 VALUES (1,1), (2,2);
    INSERT INTO t2 VALUES (1,1), (3,3);
    SELECT * FROM t1;
    SELECT * FROM t2;
    
    id val
    1 1
    2 2
    id val
    1 1
    3 3
    CREATE TRIGGER tr_au_t1
    AFTER UPDATE ON t1
    FOR EACH ROW
    BEGIN
        IF @check_for_cycle IS NULL THEN
            SET @check_for_cycle := 1;
            UPDATE t2 SET val = NEW.val + 10 WHERE id = NEW.id;
            SET @check_for_cycle := NULL;
        END IF;
    END
    
    CREATE TRIGGER tr_au_t2
    AFTER UPDATE ON t2
    FOR EACH ROW
    BEGIN
        IF @check_for_cycle IS NULL THEN
            SET @check_for_cycle := 1;
            UPDATE t1 SET val = NEW.val + 100 WHERE id = NEW.id;
            SET @check_for_cycle := NULL;
        END IF;
    END
    
    UPDATE t1 SET val = val + 1;
    SELECT * FROM t1;
    SELECT * FROM t2;
    
    id val
    1 2
    2 3
    id val
    1 12
    3 3
    UPDATE t2 SET val = val + 2;
    SELECT * FROM t1;
    SELECT * FROM t2;
    
    id val
    1 114
    2 3
    id val
    1 14
    3 5

    fiddle


    您必须检查触发器中没有错误发生,并清除错误处理程序中的变量。否则,当 INSERT 失败时,触发器中断并且整个过程回滚,但变量值将保持未清除状态(变量分配不回滚),这将锁定触发器操作以进行进一步更新。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-19
      • 2017-05-23
      • 2021-07-17
      • 1970-01-01
      • 2017-08-11
      • 2013-02-24
      • 2021-07-09
      • 1970-01-01
      相关资源
      最近更新 更多