[英]Can I make a MySQL trigger execute before the actual triggering statement?
我在子表上有一個觸發器,用於更新父表上的計數器。 無論我在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
表,從而導致整個地方都出現死鎖。)
預先感謝您的任何見解。
CREATE TRIGGER line_item_trigger BEFORE INSERT ON line_items
FOR EACH ROW
強制執行此觸發器以在插入之前調用。 無需為此做更多的事情。
請根據需要檢查提交頻率,以確保提交事務。
您是否有一個演示這種行為的示例?
以下示例從BEFORE TRIGGER
更新items
表的row_count_line_items
列,計算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 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.