MySQL的高级唯一约束

时间:2013-07-18 11:53:14

标签: mysql unique-constraint

归结为我的问题的本质我有一个带有DATETIME字段的MySQL表(InnoDB),我需要实现一个重复的检查,不允许同一个日期,直到小时,不止一次使用(例如,2013-07-18 13只有一行:xx:xx)。

我的第一个问题是,如果有任何方法可以在MySQL数据库中强制执行此操作吗?

否则我的方法将遵循:

  1. 锁定表格以进行读取和写入(以避免
  2. 进行SELECT查询以验证我是否可以插入新行
  3. 插入
  4. 再次解锁桌面
  5. 我真的不喜欢这个解决方案 - 任何关于如何在不必锁定桌子的情况下做到这一点的建议都将不胜感激。

1 个答案:

答案 0 :(得分:1)

在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