PostgreSQL 9.0 and later
PostgreSQL 9.0 has added deferred unique restrictions , which is exactly the function that you think you need. Thus, uniqueness is checked at the time of fixing, and not at the time of updating.
Create a UNIQUE constraint using the DEFERRABLE keyword:
ALTER TABLE foo ADD CONSTRAINT foo_uniq (foo_id) DEFERRABLE;
Later, before running the UPDATE statement, you perform the same transaction:
SET CONSTRAINTS foo_uniq DEFERRED;
Alternatively, you can create a constraint using the INITIALLY DEFERRED keyword on the most unique constraint - so you do not need to run SET CONSTRAINTS - but this can affect the performance of your other queries that are not needed to defer the constraint.
PostgreSQL 8.4 and later
If you want to use a unique constraint to ensure uniqueness - and not as a target for a foreign key, then this workaround can help:
First add a boolean column, such as is_temporary , to the table that temporarily distinguishes between updated and non-updated rows:
CREATE TABLE foo (value int not null, is_temporary bool not null default false);
Then create a partial unique index that only affects rows where is_temporary = false:
CREATE UNIQUE INDEX ON foo (value) WHERE is_temporary=false;
Now, every time you make the updates described by you, you launch them in two stages:
UPDATE foo SET is_temporary=true, value=value+1 WHERE value>3; UPDATE foo SET is_temporary=false WHERE is_temporary=true;
As long as these statements arise in one transaction, it will be absolutely safe - other sessions will never see temporary lines. The disadvantage is that you will write lines twice.
Please note that this is just a unique index, not a limitation, but in practice it does not matter.