簡體   English   中英

我可以在實際觸發語句之前執行MySQL觸發嗎?

[英]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

如果將事件更改為AFTERAFTER 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM