CREATE TABLE widget (
id serial PRIMARY KEY,
name text NOT NULL,
ordinal int NOT NULL UNIQUE
);
eu tenho os dados
id | name | ordinal
----+------+---------
1 | A | 1
2 | B | 2
3 | C | 3
Eu gostaria de atualizá-lo para
id | name | ordinal
----+------+---------
1 | A | 3
2 | B | 2
3 | C | 1
Tocando nos registros o mínimo possível (ou seja, não reescreva todo o conjunto de registros, não inicie gatilhos desnecessários), qual é a abordagem geralmente aplicável para atualizar ordinal
os valores de destino?
Uma atualização vanilla apenas me dá violações de restrição, mesmo que aconteça em uma única instrução.
E descartar e recriar a restrição exclusiva é uma concorrência cara e ruim.
Este parece ser um problema comum o suficiente para que deve haver uma boa maneira de fazer isso, que eu simplesmente não consigo pensar.
Defina a restrição como adiável:
Então você pode atualizá-lo em uma declaração:
UNIQUE
Uma restrição simples éNOT DEFERRABLE
por padrão. Violações únicas são verificadas após cada linha . O manual expressa isso como:Mas é realmente verificado para cada linha escrita individual.
Se você definir a
UNIQUE
restriçãoDEFERRABLE
(como a_horse fornecida), as violações exclusivas serão verificadas após cada instrução . Vários CTEs dentro da mesma consulta ainda contam como uma única instrução a esse respeito.Se você também definir a restrição como
DEFERRED
, a verificação de violações exclusivas será adiada até depois de cada transação .Demonstração completa:
db<>fique aqui
Leitura adicional: