【发布时间】:2023-04-09 05:38:02
【问题描述】:
每当我在同一个表中插入一行时,我都需要在表中插入一条折扣行。 现在我知道这可能会以无限循环结束,但我已将支票放入,因此在插入折扣行时它不会插入任何内容。
Mysql 似乎不允许这样做。它甚至不会插入到表中,更不用说触发触发器了
关于如何做到这一点的任何建议?
【问题讨论】:
每当我在同一个表中插入一行时,我都需要在表中插入一条折扣行。 现在我知道这可能会以无限循环结束,但我已将支票放入,因此在插入折扣行时它不会插入任何内容。
Mysql 似乎不允许这样做。它甚至不会插入到表中,更不用说触发触发器了
关于如何做到这一点的任何建议?
【问题讨论】:
您不能在附加到该表的触发器中更改表(当前行除外)。
一种解决方案是插入另一个表,并让该触发器将 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 ;
【讨论】:
你为什么不把你的INSERT 代码改成这样呢? :
INSERT INTO table1 (field1, field2, ...)
VALUES ( @item, @price, ....)
, ( @item, @discount, ...) ;
另一件事是重新评估您的数据结构。现在的方式似乎 - 从您提供的有限信息来看 - 它没有标准化。您在表中存储两种类型的信息。
也许您可以通过在表格中添加几列来将两行(每次都插入)合并为一个。
或者将表格拆分为两张表格,一张用于“正常”商品行,一张用于折扣商品。
【讨论】:
在 MySQL 中是不允许的。
一种解决方案是让触发器在 另一个 表中插入两次。然后,您将对写入表进行写入和更新,并从触发器管理的读取表中读取。
【讨论】:
我需要根据表聚合的特定条件向同一个表添加额外的行,但由于稳定性锁定策略,我无法更新我的应用程序查询以在数据库之外处理它。
另一种解决方案是利用 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
【讨论】: