Avec PostgreSQL, cela ne peut être résolu que de manière "agréable" en utilisant la version 9.0 car vous pouvez y définir des contraintes uniques pouvant être reportées.
Avec PostgreSQL 9.0, vous feriez simplement :
create table label (
id_label serial not null,
rank integer not null,
title text not null,
constraint pri primary key (id_label)
);
alter table label add constraint unique_rank unique (rank)
deferrable initially immediate;
Ensuite, la mise à jour est aussi simple que ceci :
begin;
set constraints unique_rank DEFERRED;
update rank
set rank = case when rank = 20 then 10 else 20 end
where id_label in (1,2);
commit;
Modifier :
Si vous ne voulez pas vous embêter à définir la contrainte comme différée dans votre transaction, vous pouvez simplement définir la contrainte comme initially deferred
.