2017-04-14 2 views
0

J'ai deux tables: warehouse et inventory:Déclencheur sur l'insert; au lieu de A faire B

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) 
); 

Je veux mettre un déclencheur de sorte que toute insertion sur inventory, si cette insertion ne dispose pas d'un nom unique, l'ajouter à warehouse aussi, sinon augmenter warehouse.qty de manière appropriée.

Si je devais insérer une ligne dans inventory:

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

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

Une ligne dans inventory a été ajouté, mais aussi une ligne warehouse. Ensuite, une autre rangée unique est ajoutée:

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

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

Enfin, un second marteau est ajouté.

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

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

Remarque lorsque la seconde insertion « marteau » est arrivé, une nouvelle ligne n'a pas été ajouté à inventory, au lieu avait son qty incrémente la ligne liée à warehouse. Comment créer ce déclencheur dans SQL?

Répondre

1

14.1.18 CREATE TABLE Syntax

...

  • Certains attributs ne sont pas applicables à tous les types de données. AUTO_INCREMENT s'applique uniquement aux types entiers et flottants. DEFAULT ne s'applique pas aux types BLOB, TEXT, GEOMETRY et JSON.

...

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

Vous pouvez avoir quelques options, avec quelques considérations:

  • Si item colonne doit suivre strictement la séquence (AUTO_INCREMENT), vous pouvez en encapsuler une procédure stockée INSERT logique:

Exemple 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 (exemple 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) 

SUR DUPL ICATE KEY UPDATE (Exemple 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)