sql >> Base de Datos >  >> RDS >> PostgreSQL

serial en postgres se está incrementando a pesar de que agregué en conflicto no hacer nada

La razón por la que esto le resulta extraño es que está pensando en el incremento en el contador como parte de la operación de inserción y, por lo tanto, "NO HACER NADA" debería significar "no incrementar nada". Te estás imaginando esto:

  1. Verifique los valores para insertar contra la restricción
  2. Si se detecta duplicado, cancelar
  3. Secuencia de incremento
  4. Insertar datos

Pero, de hecho, el incremento tiene que ocurrir antes de que se intente la inserción . Un SERIAL la columna en Postgres se implementa como DEFAULT que ejecuta nextval() función en una SEQUENCE enlazada . Antes de que DBMS pueda hacer algo con los datos, debe tener un conjunto completo de columnas, por lo que el orden de las operaciones es así:

  1. Resolver valores predeterminados, incluido el incremento de la secuencia
  2. Verifique los valores para insertar contra la restricción
  3. Si se detecta duplicado, cancelar
  4. Insertar datos

Esto se puede ver intuitivamente si la clave duplicada está en el propio campo de autoincremento:

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, esto no puede saber si hay un conflicto sin incrementar la secuencia, por lo que el "no hacer nada" tiene que venir después ese incremento.