我在子表上有一个触发器,用于更新父表上的计数器。无论我CREATE TRIGGER ... BEFORE INSERT
还是AFTER INSERT
,触发器中的SQL总是在执行之后执行。
有没有办法强制它在之前运行?
CREATE TABLE items (
id int(11) unsigned NOT NULL AUTO_INCREMENT,
quantity_sold int(11) unsigned DEFAULT 0,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE line_items (
id int(11) unsigned NOT NULL AUTO_INCREMENT,
item_id int(11) unsigned DEFAULT NULL,
quantity int(11) unsigned DEFAULT 1,
PRIMARY KEY (id),
CONSTRAINT fk FOREIGN KEY (item_id) REFERENCES items (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO items (id) VALUES (1);
DROP TRIGGER IF EXISTS line_item_trigger;
delimiter $$
CREATE TRIGGER line_item_trigger BEFORE INSERT ON line_items
FOR EACH ROW
BEGIN
UPDATE items SET quantity_sold = quantity_sold + NEW.quantity WHERE id = NEW.item_id;
END
$$
运行:
INSERT INTO line_items (item_id) VALUES (1);
...导致:
INSERT INTO line_items (item_id) VALUES (1);
UPDATE items SET quantity_sold = quantity_sold + NEW.quantity WHERE id = NEW.item_id;
我希望首先发生UPDATE
。
(为什么?这都是在事务中完成的,INSERT
在进行外键检查时锁定items
表,导致整个地方出现死锁。)
提前感谢任何见解。
答案 0 :(得分:0)
CREATE TRIGGER line_item_trigger BEFORE INSERT ON line_items
FOR EACH ROW
强制执行此触发器以在插入之前调用。没有什么需要做的了。
请根据需要检查提交频率,以确保您提交交易。
答案 1 :(得分:0)
您是否有示例演示此行为?
以下示例从row_count_line_items
更新items
表的BEFORE TRIGGER
列,计算line_items
表中的行数。由于它是BEFORE TRIGGER
,row_count_line_items
列为零(0)(此时INSERT
尚未完成):
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> DROP TRIGGER IF EXISTS `line_item_trigger`;
Query OK, 0 rows affected (0.00 sec)
mysql> DROP TABLE IF EXISTS `line_items`, `items`;
Query OK, 0 rows affected (0.01 sec)
mysql> CREATE TABLE IF NOT EXISTS `items` (
-> `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
-> `quantity_sold` int(11) unsigned DEFAULT 0,
-> `row_count_line_items` int,
-> PRIMARY KEY (`id`)
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `line_items` (
-> `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
-> `item_id` int(11) unsigned DEFAULT NULL,
-> `quantity` int(11) unsigned DEFAULT 1,
-> PRIMARY KEY (`id`),
-> CONSTRAINT `fk` FOREIGN KEY (`item_id`) REFERENCES items (`id`)
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO `items` (`id`) VALUES (1);
Query OK, 1 row affected (0.01 sec)
mysql> CREATE TRIGGER `line_item_trigger` BEFORE INSERT ON `line_items`
-> FOR EACH ROW
-> UPDATE `items`
-> SET `quantity_sold` = `quantity_sold` + NEW.`quantity`,
-> `row_count_line_items` = (SELECT COUNT(`id`)
-> FROM `line_items`)
-> WHERE `id` = NEW.`item_id`;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO `line_items` (`item_id`) VALUES (1);
Query OK, 1 row affected (0.01 sec)
mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT `id`, `quantity_sold`, `row_count_line_items`
-> FROM `items`;
+----+---------------+----------------------+
| id | quantity_sold | row_count_line_items |
+----+---------------+----------------------+
| 1 | 1 | 0 |
+----+---------------+----------------------+
1 row in set (0.00 sec)
mysql> SELECT `id`, `item_id`, `quantity`
-> FROM `line_items`;
+----+---------+----------+
| id | item_id | quantity |
+----+---------+----------+
| 1 | 1 | 1 |
+----+---------+----------+
1 row in set (0.00 sec)
请参阅db-fiddle。
如果我们将事件更改为AFTER
(AFTER TRIGGER
),那么row_count_line_items
列的值将为一(1)(因为INSERT
已经完成) :
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> DROP TRIGGER IF EXISTS `line_item_trigger`;
Query OK, 0 rows affected (0.00 sec)
mysql> DROP TABLE IF EXISTS `line_items`, `items`;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `items` (
-> `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
-> `quantity_sold` int(11) unsigned DEFAULT 0,
-> `row_count_line_items` int,
-> PRIMARY KEY (`id`)
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `line_items` (
-> `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
-> `item_id` int(11) unsigned DEFAULT NULL,
-> `quantity` int(11) unsigned DEFAULT 1,
-> PRIMARY KEY (`id`),
-> CONSTRAINT `fk` FOREIGN KEY (`item_id`) REFERENCES items (`id`)
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO `items` (`id`) VALUES (1);
Query OK, 1 row affected (0.00 sec)
mysql> CREATE TRIGGER `line_item_trigger` AFTER INSERT ON `line_items`
-> FOR EACH ROW
-> UPDATE `items`
-> SET `quantity_sold` = `quantity_sold` + NEW.`quantity`,
-> `row_count_line_items` = (SELECT COUNT(`id`)
-> FROM `line_items`)
-> WHERE `id` = NEW.`item_id`;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO `line_items` (`item_id`) VALUES (1);
Query OK, 1 row affected (0.08 sec)
mysql> SELECT `id`, `quantity_sold`, `row_count_line_items`
-> FROM `items`;
+----+---------------+----------------------+
| id | quantity_sold | row_count_line_items |
+----+---------------+----------------------+
| 1 | 1 | 1 |
+----+---------------+----------------------+
1 row in set (0.00 sec)
mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT `id`, `item_id`, `quantity`
-> FROM `line_items`;
+----+---------+----------+
| id | item_id | quantity |
+----+---------+----------+
| 1 | 1 | 1 |
+----+---------+----------+
1 row in set (0.00 sec)
请参阅db-fiddle。