【发布时间】:2017-02-21 22:00:36
【问题描述】:
我正在使用 MySQL 5.7:
D:\>mysql --version
mysql Ver 14.14 Distrib 5.7.17, for Win64 (x86_64)
根据manual,BEFORE INSERT 触发器的行为应该是:
为每一行激活一个 BEFORE INSERT 触发器,后跟一个 AFTER INSERT 触发器或 BEFORE UPDATE 和 AFTER UPDATE 同时触发 触发器,取决于该行是否存在重复键。
我认为这意味着无论是否存在重复的键匹配,都会执行 BEFORE INSERT,而 AFTER INSERT 和 UPDATE 触发器取决于是否存在键冲突。 This SO 重复相同。但是,我没有看到这种行为。这是我所做的:
create table testtable (
id integer primary key auto_increment,
nickname varchar(40), -- this is the natural key to be unique indexed
name varchar(40),
uuid varchar(36)); -- this is what I want to assign in the trigger
alter table testtable add unique index testtable_ux (nickname);
create trigger testtable_uid before insert on testtable for each row set
new.uuid=uuid();
-- get some data
insert into testtable (nickname, name) values ('bob', 'Robert'),
('fred', 'Frederick'), ('cha', 'Chauncey');
select * from testtable;
1 bob Robert 06fb18be-f87e-11e6-8e6f-0060737a7c01
2 fred Frederick 06fb1a5d-f87e-11e6-8e6f-0060737a7c01
3 cha Chauncey 06fb1aec-f87e-11e6-8e6f-0060737a7c01
很好 - 每个家伙都有一个唯一的 UUID。现在好的,根据手册,无论是否存在重复键,都应该执行此 BEFORE INSERT 触发器,所以即使我得到重复键更新,UUID 也应该更新 - 对吧?让我们看看:
insert into testtable (nickname, name) values ('fred', 'Alfred')
on duplicate key update name='Alfred';
3 88 16:39:32 ... 2 row(s) affected 0.032 sec
select * from testtable;
1 bob Robert 06fb18be-f87e-11e6-8e6f-0060737a7c01
2 fred Alfred 06fb1a5d-f87e-11e6-8e6f-0060737a7c01
3 cha Chauncey 06fb1aec-f87e-11e6-8e6f-0060737a7c01
嗯,名称已更新。让我们比较一下 UUID:
2 fred Frederick 06fb1a5d-f87e-11e6-8e6f-0060737a7c01
2 fred Alfred 06fb1a5d-f87e-11e6-8e6f-0060737a7c01
upsert 已按预期执行,但未重新生成 UUID。我已经尝试使用常量字符串并得到相同的结果。
现在,这正是我想要发生的;无论采用 upsert 的哪个分支,都发生 BEFORE INSERT 似乎毫无用处,或者至少这种行为似乎更有用。但这似乎与手册所说的相反。有什么见解吗?
【问题讨论】:
-
我的猜测:新的
uuid已生成但未分配。为什么你认为应该?你确切地告诉重复密钥应该发生什么:name='Alfred'。那么,您为什么希望 UUID 发生变化? -
@PaulSpiegel 感谢您的想法,但我在那里有“设置”。它在初始插入期间起作用 - 这就是首先填充列的方式。