De reden dat dit raar voor je voelt, is dat je denkt aan de verhoging op de teller als onderdeel van de invoegbewerking, en daarom zou "NIS DOEN" moeten betekenen "niets verhogen". Je stelt je dit voor:
- Controleer waarden om in te voegen tegen beperking
- Als duplicaat wordt gedetecteerd, afbreken
- Verhogen volgorde
- Gegevens invoegen
Maar in feite moet de verhoging plaatsvinden voordat wordt geprobeerd om in te voegen . Een SERIAL
kolom in Postgres is geïmplementeerd als een DEFAULT
die de nextval()
. uitvoert functie op een gebonden SEQUENCE
. Voordat het DBMS iets met de gegevens kan doen, moet het een complete set kolommen hebben, dus de volgorde van bewerkingen is als volgt:
- Los standaardwaarden op, inclusief het verhogen van de reeks
- Controleer waarden om in te voegen tegen beperking
- Als duplicaat wordt gedetecteerd, afbreken
- Gegevens invoegen
Dit is intuïtief te zien als de duplicaatsleutel in het autoincrement-veld zelf staat:
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;
Het is duidelijk dat dit niet kan weten of er een conflict is zonder de reeks te verhogen, dus de "niets doen" moet na komen die toename.