PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

serial no postgres está sendo aumentado, embora eu tenha adicionado conflito, não faça nada


A razão pela qual isso parece estranho para você é que você está pensando no incremento no contador como parte da operação de inserção e, portanto, "DO NOTHING" deve significar "não incremente nada". Você está imaginando isso:
  1. Verifique os valores a serem inseridos em relação à restrição
  2. Se a duplicata for detectada, cancele
  3. Sequência de incremento
  4. Inserir dados

Mas, na verdade, o incremento tem que acontecer antes que a inserção seja tentada . Um SERIAL coluna no Postgres é implementada como um DEFAULT que executa o nextval() função em uma SEQUENCE vinculada . Antes que o DBMS possa fazer qualquer coisa com os dados, ele precisa ter um conjunto completo de colunas, então a ordem das operações é assim:
  1. Resolva os valores padrão, incluindo o incremento da sequência
  2. Verifique os valores a serem inseridos em relação à restrição
  3. Se a duplicata for detectada, cancele
  4. Inserir dados

Isso pode ser visto intuitivamente se a chave duplicada estiver no próprio campo de incremento automático:
CREATE TABLE foo ( id SERIAL NOT NULL PRIMARY KEY, bar text );
-- Insert row 1
INSERT INTO foo ( bar ) VALUES ( 'test' );
-- Reset the sequence
SELECT setval(pg_get_serial_sequence('foo', 'id'), 0, true);
-- Attempt to insert row 1 again
INSERT INTO foo ( bar ) VALUES ( 'test 2' )
     ON CONFLICT (id) DO NOTHING;

Claramente, isso não pode saber se há um conflito sem incrementar a sequência, então o "não fazer nada" tem que vir depois esse incremento.