我有两个表:warehouse
和inventory
:
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中创建此触发器?
答案 0 :(得分:1)
...
- 某些属性不适用于所有数据类型。 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)
item
列不一定严格按照顺序排列
(AUTO_INCREMENT),您可以使用14.2.5 INSERT Syntax::IGNORE或14.2.5.3 INSERT ... ON DUPLICATE KEY UPDATE Syntax: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)