Corriger PG::UniqueViolation quand il n'y a pas de violation unique
Avez-vous déjà rencontré une erreur PG::UniqueViolation alors que vous êtes certain qu’il n’y a pas de données en double ? Le coupable est souvent une séquence PostgreSQL désynchronisée.
Le Problème
Vous voyez une erreur comme :
PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "users_pkey"
DETAIL: Key (id)=(42) already exists.
Mais quand vous vérifiez, il n’y a aucun enregistrement avec l’ID 42. Que se passe-t-il ?
La Cause
PostgreSQL utilise des séquences pour générer des IDs auto-incrémentés. Parfois, surtout après des importations de données ou des insertions manuelles, la séquence se désynchronise avec l’ID maximum réel dans la table.
La Solution
Réinitialisez la séquence à la valeur correcte :
SELECT setval('users_id_seq', (SELECT MAX(id) FROM users));
Ou en Rails :
ActiveRecord::Base.connection.execute(
"SELECT setval('users_id_seq', (SELECT MAX(id) FROM users))"
)
Pour Toutes les Tables
Pour corriger toutes les séquences en une fois :
ActiveRecord::Base.connection.tables.each do |table|
ActiveRecord::Base.connection.reset_pk_sequence!(table)
end
Prévention
Ce problème survient couramment après :
- Des migrations ou importations de données
- Des insertions SQL manuelles avec des IDs explicites
- La restauration depuis des sauvegardes
Réinitialisez toujours les séquences après des opérations de données en masse pour éviter ces erreurs mystérieuses.