这是一个玩具示例,说明了PostgreSQL中的一个真正的问题。以下示例使用的是PostgreSQL 8.4.3服务器,但我怀疑其他版本也有同样的问题。
鉴于下表:
=> create table tmp_foo (foo boolean not null unique, bar boolean not null unique); => insert into tmp_foo (foo, bar) values (true, true), (false, false); => select * from tmp_foo; foo | bar -----+----- t | t f | f
可以将表修改为如下所示:
=> select * from tmp_foo; foo | bar -----+----- t | f f | t
不删除行或修改表架构?这样:
=> update tmp_foo set bar = not bar; ERROR: duplicate key value violates unique constraint "tmp_foo_bar_key"
不起作用。
如果允许删除,请执行以下操作:
=> create temp table tmp_foo_2 as select * from tmp_foo; => update tmp_foo_2 set bar = not bar; => delete from tmp_foo; => insert into tmp_foo select * from tmp_foo_2;
的工作原理。对于这个例子来说,这不是最简单的解决方案,但它很容易推广到更复杂的例子。
答案 0 :(得分:3)
这样做需要可延迟的唯一约束。
每列中的行数尽可能多。因此,要改变任何行,要么某些行必须暂时违反唯一约束,要么必须删除某些行以避免违反约束。可延迟的唯一约束让我们做前者 - 临时违规(在交易中)。
如果您遵循这一点,听起来是正确的,那么您的问题的答案取决于Postgres版本。
Postgres仅限8.4 allows deferral of foreign key constraints。推论是不能推迟独特的约束。
Postgres 9.0 beta理论上提供了可延迟的唯一约束。我自己没有尝试过,但是这个功能已经很长时间了,所以我敢打赌他们在决定实现它时就做对了。以下是关于9.0 unique indices和SET CONSTRAINTS
的两个相关文档。正如您在后一个链接中所看到的,在9.0文档中通过SET CONSTRAINTS
明确列出了对延迟支持的唯一约束。我还没有探索过这个新功能,我不能保证语义正是你所需要的。但它似乎只是那件事。