【问题标题】:Special case of updating a column with not null and unique constraints in PostgreSQL在 PostgreSQL 中更新具有非空和唯一约束的列的特殊情况
【发布时间】:2011-03-18 17:05:34
【问题描述】:

这是一个说明 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;

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

【问题讨论】:

  • 这是一个有趣的问题,但我不明白你为什么不想在那里删除。您已经创建了一组非常,呃,受限的约束。您要解决的更大的问题是什么?

标签: sql postgresql constraints unique-constraint


【解决方案1】:

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

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

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

仅限 8.4 的 Postgres allows deferral of foreign key constraints。推论是不能推迟唯一约束。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-29
    • 2015-07-21
    • 2013-12-16
    • 2014-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多