PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Serien in Postgres werden erhöht, obwohl ich bei Konflikten nichts hinzugefügt habe

Der Grund, warum sich das für Sie seltsam anfühlt, ist, dass Sie an die Erhöhung des Zählers als Teil der Einfügeoperation denken, und daher sollte "NICHT TUN" bedeuten "nichts erhöhen". Du stellst dir das vor:

  1. Werte zum Einfügen gegen Beschränkung prüfen
  2. Wenn Duplikate erkannt werden, abbrechen
  3. Sequenz erhöhen
  4. Daten einfügen

Aber tatsächlich muss die Erhöhung erfolgen, bevor die Einfügung versucht wird . Eine SERIAL Spalte in Postgres ist als DEFAULT implementiert die das nextval() ausführt Funktion auf einer gebundenen SEQUENCE . Bevor das DBMS irgendetwas mit den Daten machen kann, muss es einen vollständigen Satz von Spalten haben, also ist die Reihenfolge der Operationen wie folgt:

  1. Standardwerte auflösen, einschließlich Inkrementieren der Sequenz
  2. Werte zum Einfügen gegen Beschränkung prüfen
  3. Wenn Duplikate erkannt werden, abbrechen
  4. Daten einfügen

Dies ist intuitiv zu erkennen, wenn sich der doppelte Schlüssel im Autoinkrement-Feld selbst befindet:

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;

Dies kann natürlich nicht wissen, ob es einen Konflikt gibt, ohne die Sequenz zu erhöhen, also muss das "Nichts tun" nach kommen dieses Inkrement.