La raison pour laquelle cela vous semble bizarre est que vous pensez à l'incrément sur le compteur dans le cadre de l'opération d'insertion, et donc le "NE RIEN FAIRE" devrait signifier "ne rien incrémenter". Vous imaginez ceci :
- Cochez les valeurs à insérer par rapport à la contrainte
- Si un doublon est détecté, abandonnez
- Séquence d'incrémentation
- Insérer des données
Mais en fait, l'incrément doit avoir lieu avant que l'insertion ne soit tentée . Un SERIAL
la colonne dans Postgres est implémentée en tant que DEFAULT
qui exécute le nextval()
fonction sur une SEQUENCE
liée . Avant que le SGBD puisse faire quoi que ce soit avec les données, il doit avoir un ensemble complet de colonnes, donc l'ordre des opérations est le suivant :
- Résoudre les valeurs par défaut, y compris l'incrémentation de la séquence
- Cochez les valeurs à insérer par rapport à la contrainte
- Si un doublon est détecté, abandonnez
- Insérer des données
Cela peut être vu intuitivement si la clé en double se trouve dans le champ d'auto-incrémentation lui-même :
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;
De toute évidence, cela ne peut pas savoir s'il y a un conflit sans incrémenter la séquence, donc le "ne rien faire" doit venir après cet incrément.