插入时触发;而不是A做B.

时间:2017-04-14 18:11:19

标签: mysql sql triggers database-trigger

我有两个表:warehouseinventory

CREATE TABLE warehouse (
    bin VARCHAR(6) NOT NULL AUTO_INCREMENT,
    qty INT
    PRIMARY KEY(bin)
);

CREATE TABLE inventory (
    item INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(10),
    PRIMARY KEY(item)
);

我想设置一个触发器,以便inventory上的任何插入(如果该插入没有唯一名称)也将其添加到warehouse,否则会适当增加warehouse.qty。 / p>

如果我要在inventory中插入一行:

INSERT INTO inventory 
VALUES('', 'hammer");

 inventory         warehouse
----------------------------
item | name        bin | qty
----------------------------
 1    hammer        1     1

已添加inventory中的行,但warehouse中也有一行。然后添加另一个唯一行:

INSERT INTO inventory 
VALUES('', 'pliers");

 inventory         warehouse
----------------------------
item | name        bin | qty
----------------------------
 1    hammer        1     1
 2    pliers        2     1

最后添加第二把锤子。

INSERT INTO inventory 
VALUES('', 'hammer");

 inventory         warehouse
----------------------------
item | name        bin | qty
----------------------------
 1    hammer        1     2
 2    pliers        2     1

注意第二次“锤子”插入时,inventory没有添加新行,而warehouse中的相关行的qty增加了。

如何在SQL中创建此触发器?

1 个答案:

答案 0 :(得分:1)

  

14.1.18 CREATE TABLE Syntax

     

...

     
      
  • 某些属性不适用于所有数据类型。 AUTO_INCREMENT仅适用于整数和浮点类型。 DEFAULT不适用于BLOB,TEXT,GEOMETRY和JSON类型。
  •   
     

...

CREATE TABLE warehouse (
    bin VARCHAR(6) NOT NULL AUTO_INCREMENT, -- <- It's not possible
    qty INT,
    PRIMARY KEY(bin)
);

您可能有一些选择,但有一些注意事项:

  • 如果item列必须严格遵循序列(AUTO_INCREMENT),则可以封装在存储过程INSERT逻辑中:

示例Rextester

mysql> DROP PROCEDURE IF EXISTS `insert_inventory`;
Query OK, 0 rows affected (0.00 sec)

mysql> DROP TABLE IF EXISTS `warehouse`, `inventory`;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE `warehouse` (
    ->     `bin` VARCHAR(6) NOT NULL,
    ->     `qty` INT DEFAULT 1,
    ->     PRIMARY KEY(`bin`)
    -> );
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE `inventory` (
    ->     `item` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    ->     `name` VARCHAR(10),
    ->     PRIMARY KEY(`item`),
    ->     UNIQUE KEY(`name`)
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TRIGGER `trg_ai_inventory` AFTER INSERT ON `inventory`
    -> FOR EACH ROW
    ->     INSERT INTO `warehouse` (`bin`)
    ->     VALUES (NEW.`item`);
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER //

mysql> CREATE PROCEDURE `insert_inventory`(`_name` VARCHAR(10))
    -> BEGIN
    ->     DECLARE `_item` INT DEFAULT (SELECT `item`
    ->                                  FROM `inventory`
    ->                                  WHERE `name` = `_name`);
    ->     IF `_item` IS NULL THEN
    ->         INSERT INTO `inventory` (`name`)
    ->         VALUES (`_name`);
    ->     ELSE
    ->         UPDATE `warehouse`
    ->         SET `qty` = `qty` + 1
    ->         WHERE `bin` = `_item`;
    ->     END IF;
    -> END//
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ;

mysql> CALL `insert_inventory`('hammer');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT `item`, `name`
    -> FROM `inventory`;
+------+--------+
| item | name   |
+------+--------+
|    1 | hammer |
+------+--------+
1 row in set (0.00 sec)

mysql> SELECT `bin`, `qty`
    -> FROM `warehouse`;
+-----+------+
| bin | qty  |
+-----+------+
| 1   |    1 |
+-----+------+
1 row in set (0.00 sec)

mysql> CALL `insert_inventory`('hammer');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT `item`, `name`
    -> FROM `inventory`;
+------+--------+
| item | name   |
+------+--------+
|    1 | hammer |
+------+--------+
1 row in set (0.00 sec)

mysql> SELECT `bin`, `qty`
    -> FROM `warehouse`;
+-----+------+
| bin | qty  |
+-----+------+
| 1   |    2 |
+-----+------+
1 row in set (0.00 sec)

mysql> CALL `insert_inventory`('pliers');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT `item`, `name`
    -> FROM `inventory`;
+------+--------+
| item | name   |
+------+--------+
|    1 | hammer |
|    2 | pliers |
+------+--------+
2 rows in set (0.00 sec)

mysql> SELECT `bin`, `qty`
    -> FROM `warehouse`;
+-----+------+
| bin | qty  |
+-----+------+
| 1   |    2 |
| 2   |    1 |
+-----+------+
2 rows in set (0.00 sec)

IGNORE(示例Rextester):

mysql> DROP TABLE IF EXISTS `warehouse`, `inventory`;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE `warehouse` (
    ->     `bin` VARCHAR(6) NOT NULL,
    ->     `qty` INT DEFAULT 1,
    ->     PRIMARY KEY(`bin`)
    -> );
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE `inventory` (
    ->     `item` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    ->     `name` VARCHAR(10),
    ->     PRIMARY KEY(`item`),
    ->     UNIQUE KEY(`name`)
    -> );
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER //

mysql> CREATE TRIGGER `trg_bi_inventory` BEFORE INSERT ON `inventory`
    -> FOR EACH ROW
    -> BEGIN
    ->     DECLARE `_item` INT DEFAULT (SELECT `item`
    ->                                  FROM `inventory`
    ->                                  WHERE `name` = NEW.`name`);
    ->     IF `_item` IS NOT NULL THEN
    ->         UPDATE `warehouse`
    ->         SET `qty` = `qty` + 1
    ->         WHERE `bin` = `_item`;
    ->     END IF;
    -> END//
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ;

mysql> CREATE TRIGGER `trg_ai_inventory` AFTER INSERT ON `inventory`
    -> FOR EACH ROW
    ->     INSERT INTO `warehouse` (`bin`)
    ->     VALUES (NEW.`item`);
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT IGNORE `inventory` (`name`)
    -> VALUES ('hammer');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT `item`, `name`
    -> FROM `inventory`;
+------+--------+
| item | name   |
+------+--------+
|    1 | hammer |
+------+--------+
1 row in set (0.00 sec)

mysql> SELECT `bin`, `qty`
    -> FROM `warehouse`;
+-----+------+
| bin | qty  |
+-----+------+
| 1   |    1 |
+-----+------+
1 row in set (0.00 sec)

mysql> INSERT IGNORE `inventory` (`name`)
    -> VALUES ('hammer');
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT `item`, `name`
    -> FROM `inventory`;
+------+--------+
| item | name   |
+------+--------+
|    1 | hammer |
+------+--------+
1 row in set (0.00 sec)

mysql> SELECT `bin`, `qty`
    -> FROM `warehouse`;
+-----+------+
| bin | qty  |
+-----+------+
| 1   |    2 |
+-----+------+
1 row in set (0.00 sec)

mysql> INSERT IGNORE `inventory` (`name`)
    -> VALUES ('pliers');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT `item`, `name`
    -> FROM `inventory`;
+------+--------+
| item | name   |
+------+--------+
|    1 | hammer |
|    3 | pliers |
+------+--------+
2 rows in set (0.00 sec)

mysql> SELECT `bin`, `qty`
    -> FROM `warehouse`;
+-----+------+
| bin | qty  |
+-----+------+
| 1   |    2 |
| 3   |    1 |
+-----+------+
2 rows in set (0.00 sec)

ON DUPLICATE KEY UPDATE(示例Rextester):

mysql> DROP TABLE IF EXISTS `warehouse`, `inventory`;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE `warehouse` (
    ->     `bin` VARCHAR(6) NOT NULL,
    ->     `qty` INT DEFAULT 1,
    ->     PRIMARY KEY(`bin`)
    -> );
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE `inventory` (
    ->     `item` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    ->     `name` VARCHAR(10),
    ->     `count` INT DEFAULT 1,
    ->     PRIMARY KEY(`item`),
    ->     UNIQUE KEY(`name`)
    -> );
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TRIGGER `trg_ai_inventory` AFTER INSERT ON `inventory`
    -> FOR EACH ROW
    ->     INSERT INTO `warehouse` (`bin`)
    ->     VALUES (NEW.`item`);
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TRIGGER `trg_au_inventory` AFTER UPDATE ON `inventory`
    -> FOR EACH ROW
    ->     UPDATE `warehouse`
    ->     SET `qty` = `qty` + 1
    ->     WHERE `bin` = OLD.`item`;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO `inventory` (`name`)
    -> VALUES ('hammer')
    ->     ON DUPLICATE KEY UPDATE `count` = `count` + 1;
Query OK, 1 row affected (0.00 sec)

mysql> SELECT `item`, `name`
    -> FROM `inventory`;
+------+--------+
| item | name   |
+------+--------+
|    1 | hammer |
+------+--------+
1 row in set (0.00 sec)

mysql> SELECT `bin`, `qty`
    -> FROM `warehouse`;
+-----+------+
| bin | qty  |
+-----+------+
| 1   |    1 |
+-----+------+
1 row in set (0.00 sec)

mysql> INSERT INTO `inventory` (`name`)
    -> VALUES ('hammer')
    ->     ON DUPLICATE KEY UPDATE `count` = `count` + 1;
Query OK, 2 rows affected (0.00 sec)

mysql> SELECT `item`, `name`
    -> FROM `inventory`;
+------+--------+
| item | name   |
+------+--------+
|    1 | hammer |
+------+--------+
1 row in set (0.00 sec)

mysql> SELECT `bin`, `qty`
    -> FROM `warehouse`;
+-----+------+
| bin | qty  |
+-----+------+
| 1   |    2 |
+-----+------+
1 row in set (0.00 sec)

mysql> INSERT INTO `inventory` (`name`)
    -> VALUES ('pliers')
    ->     ON DUPLICATE KEY UPDATE `count` = `count` + 1;
Query OK, 1 row affected (0.00 sec)

mysql> SELECT `item`, `name`
    -> FROM `inventory`;
+------+--------+
| item | name   |
+------+--------+
|    1 | hammer |
|    3 | pliers |
+------+--------+
2 rows in set (0.00 sec)

mysql> SELECT `bin`, `qty`
    -> FROM `warehouse`;
+-----+------+
| bin | qty  |
+-----+------+
| 1   |    2 |
| 3   |    1 |
+-----+------+
2 rows in set (0.00 sec)