归结为我的问题的本质,我有一个带有 DATETIME 字段的 MySQL 表 (InnoDB),我需要实现重复检查,不允许多次使用相同的日期,精确到小时(例如,只有一行 2013-07-18 13:xx:xx)。
那么我的第一个问题是,是否有任何方法可以在 MySQL 数据库本身中强制执行此操作?
否则我的方法是:
- 为读写锁定表(避免
- 进行 SELECT 查询以验证我可以插入新行
- 插入
- 再次解锁 table
我真的不喜欢这个解决方案 - 任何关于如何在不锁定表的情况下执行此操作的建议都将不胜感激。
最佳答案
在 MySQL 中没有简单的、声明式的方法来做到这一点。但是您可以创建一个阴影列,并使用触发器来保持数据的一致性。这假设“ts”(下方)可以是任何有效的时间戳,但您每小时只需要其中一个。
create table test (
ts datetime not null,
ts_uniq char(13) not null,
unique (ts_uniq)
);
列“ts_uniq”是阴影列。它将包含像“2013-01-01 08”这样的字符串。
create trigger bef_ins_test
before insert on test
for each row
set new.ts_uniq = date_format(new.ts, '%Y-%m-%d %H');
您需要一个在更新前执行的类似触发器。
create trigger bef_upd_test
before update on test
for each row
set new.ts_uniq = date_format(new.ts, '%Y-%m-%d %H');
当您为“ts”插入值时,阴影列会自动正确设置。
insert into test (ts) values ('2013-01-01 08:35:33');
select * from test;
ts ts_uniq
--
2013-01-01 08:35:33 2013-01-01 08
尝试插入略有不同的值会正确失败,并引发错误代码 1062(重复输入)。
insert into test (ts) values ('2013-01-01 08:47:13');
如果您更新现有时间戳,BEFORE UPDATE 触发器会保持列“ts_uniq”一致。
update test
set ts = '2013-01-01 17:42:42';
select * from test;
ts ts_uniq
--
2013-01-01 17:42:42 2013-01-01 17
尝试独立更新“ts_uniq”不会引发错误,但也不会更改行。
update test
set ts_uniq = '2013-12-31 18';
select * from test;
ts ts_uniq
--
2013-01-01 17:42:42 2013-01-01 17
关于mysql - MySQL 的高级唯一约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17722732/