1

这是一个玩具示例,说明了 PostgreSQL 中的一个实际问题。以下示例使用的是 PostgreSQL 8.4.3 服务器,但我怀疑其他版本也有同样的问题。

给定下表:

=> 创建表 tmp_foo (foo boolean not null unique, bar boolean not null unique);
=> 插入 tmp_foo (foo, bar) 值 (true, true), (false, false);
=> 从 tmp_foo 中选择 *;
 富 | 酒吧
-----+-----
 吨 | 吨
 f | F

可以将表格修改为如下所示:

=> 从 tmp_foo 中选择 *;
 富 | 酒吧
-----+-----
 吨 | F
 f | 吨

不删除行或修改表架构?这个:

=> 更新 tmp_foo 设置 bar = not bar;
错误:重复键值违反唯一约束“tmp_foo_bar_key”

不起作用。

如果允许删除,则:

=> create temp table tmp_foo_2 as select * from tmp_foo;
=> 更新 tmp_foo_2 设置 bar = not bar;
=> 从 tmp_foo 中删除;
=> 插入 tmp_foo select * from tmp_foo_2;

作品。对于这个例子来说,它不是最简单的解决方案,但它很容易推广到更复杂的例子。

4

1 回答 1

3

这样做需要可延迟的唯一约束。

我们在每一列中有尽可能多的行唯一值。因此,要改变任何行,要么必须暂时违反唯一约束,要么必须删除某些行以避免违反约束。可延迟的唯一约束让我们做前者——临时违规(在事务内)。

如果您遵循这一点,并且听起来正确,那么您的问题的答案取决于 Postgres 版本。

最高 8.4 的 Postgres 只允许延迟外键约束。推论是不能推迟唯一约束。

Postgres 9.0 beta 理论上提供了可延迟的唯一约束。我自己没有尝试过,但是这个功能已经很久了,所以我敢打赌,当他们决定实施它时,他们做对了。

以下是关于 9.0 的唯一索引SET CONSTRAINTS. SET CONSTRAINTS正如您在后一个链接中看到的那样,在 9.0 文档中明确列出了支持延迟通过的唯一约束。我还没有探索过这个新特性,我不能保证语义正是你所需要的。但这似乎只是事情。

于 2010-07-20T22:46:07.743 回答