Con PostgreSQL, esto solo se puede resolver de una manera "agradable" con la versión 9.0 porque puede definir restricciones únicas para que sean diferibles allí.
Con PostgreSQL 9.0 simplemente haría:
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;
Entonces la actualización es tan simple como esto:
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;
Editar:
Si no quiere molestarse en configurar la restricción como diferida dentro de su transacción, simplemente puede definir la restricción como initially deferred
.