插入行后,您无法再修改该值。因此SET NEW.column
仅在BEFORE
触发器中可用。
您也不能使用常规UPDATE
,因为:
存储的函数或触发器不能修改已被调用函数或触发器的语句使用(用于读取或写入)的表。
最后,在BEFORE INSERT
触发器中,该AUTO_INCREMENT
值尚未生成,并且NEW.id
是0
。
诀窍:在BEFORE
触发器中,手动检查表定义中的下一个AUTO_INCREMENT
值:
警告:这只适用于 MyISAM,不适用于 InnoDB
我想它可以与 InnoDB 一起使用,innodb_autoinc_lock_mode = 0
但我无法确定。
DELIMITER //
CREATE TRIGGER insertTable1 BEFORE INSERT ON Table1 FOR EACH ROW
BEGIN
DECLARE next_ai INT;
SELECT auto_increment INTO next_ai
FROM information_schema.tables
WHERE table_schema=DATABASE() AND table_name = 'Table1';
SET NEW.hash = calc_hash_udf(next_ai);
END //
DELIMITER ;
[编辑 1]
至于这种方法的并发证明属性,我可以说:
InnoDB 使用称为表级 AUTO-INC 锁的特殊锁来插入具有 AUTO_INCREMENT 列的表。这个锁通常被持有到语句的结尾
我想在这种情况下这是安全的。
我不熟悉这些概念,所以我无法确定。看起来确实很可疑。
[编辑 2]
我已经使用不同的设置运行了以下测试innodb_autoinc_lock_mode
:
CREATE TABLE t (ai INT AUTO_INCREMENT PRIMARY KEY, trigval INT, flag BOOL);
表上的触发器SET NEW.trigval = next_ai
使用上述方法。
在一个事务中,一个长 INSERT 是由:
INSERT INTO t SELECT null, null, 0 FROM (SELECT * FROM a_very_big_table) AS tmp;
在第二次交易中,我不断发出以下声明:
INSERT INTO t VALUES (null, null, 1);
最后,我搜索差异:
SELECT * FROM t WHERE ai <> trigval;
使用innodb_autoinc_lock_mode = 0
("traditional") 似乎是安全的。任何并发插入表的尝试都被锁定,直到 long 完成INSERT
。
但是,我没想到,使用模式1
(默认)和2
,这种方法显然是错误的。information_schema.tables.auto_increment
是按步骤更新的。这是我得到的结果:
+--------+---------+------+
| 艾| 三角 | 标志 |
+--------+---------+------+
| 3 | 4 | 0 |
| 5 | 8 | 0 |
| 9 | 16 | 0 |
| 17 | 32 | 0 |
| 33 | 64 | 0 |
| 65 | 128 | 0 |
...