【问题标题】:Insert into same table trigger mysql插入同一张表触发mysql
【发布时间】:2023-04-09 05:38:02
【问题描述】:

每当我在同一个表中插入一行时,我都需要在表中插入一条折扣行。 现在我知道这可能会以无限循环结束,但我已将支票放入,因此在插入折扣行时它不会插入任何内容。

Mysql 似乎不允许这样做。它甚至不会插入到表中,更不用说触发触发器了

关于如何做到这一点的任何建议?

【问题讨论】:

    标签: mysql triggers insert


    【解决方案1】:

    您不能在附加到该表的触发器中更改表(当前行除外)。

    一种解决方案是插入另一个表,并让该触发器将 2 行插入您感兴趣的表中。

    如果您将另一个表设为blackhole,则不必担心存储问题。

    DELIMITER $$
    
    CREATE TRIGGER ai_bh_test_each AFTER INSERT ON bh_test FOR EACH ROW
    BEGIN
      INSERT INTO table1 (field1, field2, ...) VALUES (new.field1, new.field2, ....);
      INSERT INTO table1 ... values for the second row
    END $$
    
    DELIMITER ;
    

    【讨论】:

    • 是的,我已经看到了这个解决方案,但希望有人设法调整无嵌套触发器规则
    • @Jed,对不起,这是不可能的,其他数据库在触发器中有相同的限制。触发器绝不允许直接或间接更改连接到触发器的表,否则可能会出现死循环。因此,即使您让 table1 上的触发器对 table2 执行某些操作,而 table2 的触发器会反过来影响 table1,MySQL 也会拒绝这样做。再多的嵌套也无济于事。 (我为此感到非常高兴)
    【解决方案2】:

    你为什么不把你的INSERT 代码改成这样呢? :

    INSERT INTO table1 (field1, field2, ...) 
    VALUES ( @item, @price, ....)
         , ( @item, @discount, ...) ;
    

    另一件事是重新评估您的数据结构。现在的方式似乎 - 从您提供的有限信息来看 - 它没有标准化。您在表中存储两种类型的信息。

    也许您可以通过在表格中添加几列来将两行(每次都插入)合并为一个。

    或者将表格拆分为两张表格,一张用于“正常”商品行,一张用于折扣商品。

    【讨论】:

    • 是的,我想我将不得不走这条路。
    【解决方案3】:

    在 MySQL 中是不允许的。

    一种解决方案是让触发器在 另一个 表中插入两次。然后,您将对写入表进行写入和更新,并从触发器管理的读取表中读取。

    【讨论】:

    • 试试这个方法,不行。 Mysql 也可以防止这种情况发生。
    【解决方案4】:

    我需要根据表聚合的特定条件向同一个表添加额外的行,但由于稳定性锁定策略,我无法更新我的应用程序查询以在数据库之外处理它。

    另一种解决方案是利用 MySQL 中的Events 来读取保存待处理更改的“staging” 表。这是通过消除触发器引起的循环引用来实现的。然后,该事件通过使用会话变量提前离开触发器来执行所需的更改,而无需启动触发器。请根据您的需要修改活动时间,例如EVERY 5 SECOND

    暂存表

    CREATE TABLE `table_staging` (
       `id` INT NOT NULL,
       `value` VARCHAR(250) NOT NULL,
       `added` TINYINT(1) NOT NULL DEFAULT '0',
       PRIMARY KEY (`id`)
    );
    

    触发器

    CREATE TRIGGER `table_after_insert` AFTER INSERT ON `table` FOR EACH ROW 
    tableTrigger: BEGIN
    
        IF @EXIT_TRIGGER IS NOT NULL THEN
            /* do not execute the trigger */
            LEAVE tableTrigger;
        END IF;
    
        /* insert the record into staging table if it does not already exist */
        INSERT IGNORE INTO `table_staging`(`id`, `value`)
        VALUES (NEW.id, 'custom value');
    
    END;
    

    事件

    CREATE EVENT `table_staging_add`
        ON SCHEDULE
            EVERY 1 MINUTE STARTS '2020-03-31 18:16:48'
        ON COMPLETION NOT PRESERVE
        ENABLE
        COMMENT ''
        DO BEGIN
    
        /* avoid executing if the event is currently running */
        IF @EXIT_TRIGGER IS NULL THEN
    
            SET @EXIT_TRIGGER=TRUE;
    
            /* add the values that have not already been updated */
            INSERT INTO table(`value`)
            SELECT 
                ts.value
            FROM table_staging AS ts
            WHERE ts.added = 0;
    
            /* update the records to exclude them on the next pass */
            UPDATE table_staging AS ts
            SET ts.added = 1;
    
            /* alternatively remove all the records from the staging table */
            /* TRUNCATE table_staging; */
    
            /* reset the state of execution */
            SET @EXIT_TRIGGER=NULL;
    
        END IF;
    END;
    
    

    注意事项

    确保在您的 MySQL 配置中启用event scheduler(Windows 上的 my.ini 或 Linux 上的 my.cnf)。

    [mysqld]
    event_scheduler = ON
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-02
      • 1970-01-01
      • 1970-01-01
      • 2016-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多