PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

serial in postgres viene aumentato anche se ho aggiunto in conflitto non fare nulla

Il motivo per cui ti sembra strano è che stai pensando all'incremento sul contatore come parte dell'operazione di inserimento, e quindi "NON FARE" dovrebbe significare "non incrementare nulla". Stai immaginando questo:

  1. Controlla i valori da inserire rispetto al vincolo
  2. Se viene rilevato un duplicato, interrompere
  3. Sequenza di incremento
  4. Inserisci dati

Ma in effetti, l'incremento deve avvenire prima di tentare l'inserimento . Un SERIAL la colonna in Postgres è implementata come DEFAULT che esegue nextval() funzione su un SEQUENCE legato . Prima che il DBMS possa fare qualsiasi cosa con i dati, deve avere un set completo di colonne, quindi l'ordine delle operazioni è questo:

  1. Risolvi i valori predefiniti, incluso l'incremento della sequenza
  2. Controlla i valori da inserire rispetto al vincolo
  3. Se viene rilevato un duplicato, interrompere
  4. Inserisci dati

Questo può essere visto intuitivamente se la chiave duplicata si trova nel campo di autoincremento stesso:

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;

Chiaramente, questo non può sapere se c'è un conflitto senza incrementare la sequenza, quindi il "non fare nulla" deve venire dopo quell'incremento.