问题描述
我使用 MysqL 5.6 和 item
表 (InnoDB),如下所示。
姓名 | 类型 |
---|---|
item_id | int(11) |
item_code | varchar(20) |
名称 | varchar(100) |
cat_type | varchar(50) |
prod_grp | varchar(12) |
股票 | int(11) |
价格 | 双重 |
添加日期 | 时间戳 |
item_id
列是一个 AUTO_INCREMENT
字段。
还有另外两个表,分别称为 products
和 category
。
products
表有 prod_grp
和 prod_code
列。
category
表有 cat_type
和 cat_code
列。
item_code
表的 item
是通过连接 item_id
、{{1} } 和 cat_code
表。
我为 prod_code
表定义了一个触发器,它可以在 item
表中有 category
时自动更新 products
。
item
当我进行如下插入时,触发器会正常工作并按预期更新 item_code。
item_code
比如说,如果最后一个 INSERT
是 723,那么 item
被更新为“MM-hm-hk-724”,因为 724 是下一个 DELIMITER $$
CREATE TRIGGER `add_item_code`
BEFORE INSERT ON `item`
FOR EACH ROW
BEGIN
IF (NEW.item_code IS NULL OR NEW.item_code = '' ) THEN
SET NEW.item_code = (
SELECT CONCAT("MM-",cat_code,"-",prod_code,id.item_id)
FROM products,category,(SELECT AUTO_INCREMENT AS item_id
FROM informatION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'comdb'
AND TABLE_NAME = 'item') AS id
WHERE products.prod_grp = NEW.prod_grp
AND category.cat_type = NEW.cat_type
);
END IF;
END; $$
DELIMITER ;
值。>
但是,当我使用多个值进行插入时,INSERT INTO `item`
(`prod_grp`,`name`,`stock`,`price`,`cat_type`)
VALUES ('h & k','Crooks mirror','10','333.5','home')
值变为最新的值,从而导致错误的 item_id
。
item_code
比如说,如果最后一个 AUTO_INCREMENT
是 723,那么 AUTO_INCREMENT
会为这三个项目更新如下
item_id | item_code |
---|---|
724 | MM-hm-hk-724 |
725 | MM-tl-dy-727 |
726 | MM-el-hk-727 |
如您所见,最后两个 item_code 更新为错误的 item_id。 我根本不明白发生了什么。有人可以帮忙解决这个问题吗?
解决方法
一个技巧 - 您可以尝试使用用户定义的变量。
CREATE TRIGGER `add_item_code`
BEFORE INSERT ON `item`
FOR EACH ROW
BEGIN
IF (NEW.item_code IS NULL OR NEW.item_code = '' ) THEN
IF @add_item_code_autoincrement IS NULL THEN
SELECT AUTO_INCREMENT
INTO @add_item_code_autoincrement
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'item';
END IF;
SET NEW.item_code = CONCAT("MM-",@add_item_code_autoincrement);
SET @add_item_code_autoincrement = @add_item_code_autoincrement + 1;
END IF;
END;
https://dbfiddle.uk/?rdbms=mysql_5.6&fiddle=97a725cd6a3850d52e6548ac1f09778c
这只是一个示例,因此删除了从其他表中检索值。变量名必须长而复杂,以避免任何干扰。
注意!此代码在并发插入中绝对不安全。如果执行并发插入,则此代码很可能会产生错误的值。如果您使用 INSERT .. ON DUPLICATE KEY UPDATE,它也会给出错误的结果。
此外,即使在最有利的条件下,此代码也可能给出错误的结果。因此,如果您仍然决定使用此技巧,请创建服务事件过程,该过程将检查生成值的正确性并在生成错误时更正它们。例如,它可以每分钟执行一次,并检查不超过 2 分钟的行。
额外的表格将是一种矫枉过正。但我很想知道解决方案。 – 死神
示意图:
CREATE additional_table (id INT AUTO_INCREMENT PRIMARY KEY)
AUTO_INCREMENT = {current AUTO_INCREMENT value for `item` table} ;
CREATE TRIGGER `add_item_code`
BEFORE INSERT ON `item`
FOR EACH ROW
BEGIN
INSERT INTO additional_table VALUES (DEFAULT);
SET @add_item_code_autoincrement := LAST_INSERT_ID();
-- DELETE FROM additional_table WHERE id < @add_item_code_autoincrement;
IF (NEW.item_code IS NULL OR NEW.item_code = '' ) THEN
SET NEW.item_code = CONCAT("MM-",@add_item_code_autoincrement);
END IF;
END;