Corrigiendo PG::UniqueViolation cuando no hay violación única
¿Alguna vez has encontrado un error PG::UniqueViolation cuando estás seguro de que no hay datos duplicados? El culpable suele ser una secuencia de PostgreSQL que está desincronizada.
El Problema
Ves un error como:
PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "users_pkey"
DETAIL: Key (id)=(42) already exists.
Pero cuando verificas, no hay ningún registro con ID 42. ¿Qué está pasando?
La Causa
PostgreSQL usa secuencias para generar IDs auto-incrementales. A veces, especialmente después de importaciones de datos o inserciones manuales, la secuencia se desincroniza con el ID máximo real en la tabla.
La Solución
Restablece la secuencia al valor correcto:
SELECT setval('users_id_seq', (SELECT MAX(id) FROM users));
O en Rails:
ActiveRecord::Base.connection.execute(
"SELECT setval('users_id_seq', (SELECT MAX(id) FROM users))"
)
Para Todas las Tablas
Para corregir todas las secuencias a la vez:
ActiveRecord::Base.connection.tables.each do |table|
ActiveRecord::Base.connection.reset_pk_sequence!(table)
end
Prevención
Este problema ocurre comúnmente después de:
- Migraciones o importaciones de datos
- Inserciones SQL manuales con IDs explícitos
- Restauración desde backups
Siempre restablece las secuencias después de operaciones masivas de datos para evitar estos errores misteriosos.