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:
- Controlla i valori da inserire rispetto al vincolo
- Se viene rilevato un duplicato, interrompere
- Sequenza di incremento
- 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:
- Risolvi i valori predefiniti, incluso l'incremento della sequenza
- Controlla i valori da inserire rispetto al vincolo
- Se viene rilevato un duplicato, interrompere
- 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.