Postgresql 条件唯一约束未正确更新

Postgresql 条件唯一约束未正确更新,postgresql,Postgresql,我需要在一列上强制唯一性,但仅当另一列为true时。例如: create temporary table test(id serial primary key, property character varying(50), value boolean); insert into test(property, value) values ('a', false); insert into test(property, value) values ('a', true); insert into

我需要在一列上强制唯一性,但仅当另一列为true时。例如:

create temporary table test(id serial primary key, property character varying(50), value boolean);
insert into test(property, value) values ('a', false);
insert into test(property, value) values ('a', true);
insert into test(property, value) values ('a', false);
我用条件索引强制唯一性:

create unique index on test(property) where value = true;
到目前为止,当我尝试更改值设置为true的行时,问题就出现了。如果我这样做,它会起作用:

update test set value = new_value from (select id, id=3 as new_value from test where property = 'a')new_test where test.id = new_test.id
但当我这样做的时候,情况就不一样了:

update test set value = new_value from (select id, id=1 as new_value from test where property = 'a')new_test where test.id = new_test.id
我得到:

ERROR:  duplicate key value violates unique constraint "test_property_idx"
DETAIL:  Key (property)=(a) already exists.

********** Error **********

ERROR: duplicate key value violates unique constraint "test_property_idx"
SQL state: 23505
Detail: Key (property)=(a) already exists.
基本上,如果值为true的行的主键的值大于当前值为truthy的行,则它可以工作。有没有办法绕过它

我当然可以做到:

update test set value = false where property='a';
update test set value = true where property = 'a' and id = 1;
然而,我正在从节点运行这些查询,最好只运行一个查询

我使用的是Postgres9.5,您的问题是(它可以在某些RDBMS中使用,但在PostgreSQL中不能使用)

通常的解决方案是使约束可延迟。但是您使用的是部分唯一索引&索引不能声明为可延迟的

改用一个:它们是唯一约束的泛化&也可以是局部约束

ALTER TABLE test
  ADD EXCLUDE (property WITH =) WHERE (value = true)
  DEFERRABLE INITIALLY DEFERRED;

尝试将唯一约束设为可延迟的初始延迟。不幸的是,不确定语法。实际上似乎不可能使用唯一索引,只有使用约束唯一存储函数来更新数据<代码>更新测试集值=false,其中property='a'和value将更有效率。顺便说一句,更新测试集值=id=3,其中属性=a更简单。