bod*_*odo 5 mysql innodb trigger auto-increment
与 MySQL MyISAM-Engine 相比,InnoDB-Engine 无法处理复合主键的一列声明为AUTO_INCREMENT. 例如,考虑下表:
CREATE TABLE `ExampleTable` (
`KeyPartA` mediumint(8) unsigned NOT NULL,
`KeyPartB` smallint(5) unsigned NOT NULL,
`Data` text NOT NULL,
PRIMARY KEY (`KeyPartA`,`KeyPartB`)
) ENGINE=InnoDB;
Run Code Online (Sandbox Code Playgroud)
现在模拟AUTO_INCREMENT,我了解到,可以创建以下触发器
DELIMITER $$
CREATE TRIGGER ExampleAutoIncrement BEFORE INSERT ON ExampleTable
FOR EACH ROW BEGIN
SET NEW.KeyPartB = (
SELECT IFNULL(MAX(KeyPartB), 0) + 1
FROM ExampleTable
WHERE KeyPartA = NEW.KeyPartA
);
END $$
DELIMITER ;
Run Code Online (Sandbox Code Playgroud)
现在插入工作正常,生成自动递增的值。不幸的是,我想不出一种明智的方法来获取新创建的键值。
由于LAST_INSERT_ID()没有实际的AUTO_INCREMENT列,因此它的 C 对应项都不会返回它。也不能LAST_INSERT_ID(IFNULL(MAX(KeyPartB), 0) + 1)在ExampleAutoIncrement触发器内部设置值,因为 MySQL 在触发器完成后重置该值。
我想到的唯一方法是SELECT MAX(KeyPartB) FROM ExampleTable WHERE KeyPartA = ?在插入后发出 a ,这违背了触发器的全部目的。即我也可以在插入和手动增量之前执行此操作。
有没有办法从触发器或其他模拟AUTO_INCREMENT我想要的方法中获取递增的键值?
我的解决方案是从 myisam 迁移到 innodb。它是这样的:
BEGIN;
SELECT @id := IFNULL(MAX(id),0) + 1 FROM foo WHERE other = 123 FOR UPDATE;
INSERT INTO foo
(other, id, ...)
VALUES
(123, @id, ...);
COMMIT;
Run Code Online (Sandbox Code Playgroud)
必须进行事务以防止另一个线程获取相同的 id。