El valor de la clave duplicada de IntegrityError viola la restricción única – django / postgres

Estoy dando seguimiento a una pregunta que hice antes, en la que busqué una conversión de una consulta misteriosa / mal escrita de mysql a postgresql. Creo que tuve éxito con eso. De todos modos, estoy usando datos que se movieron manualmente desde una base de datos mysql a una base de datos postgres. Estoy usando una consulta que se ve así:

""" UPDATE krypdos_coderound cru set is_correct = case when t.kv_values1 = t.kv_values2 then True else False end from (select cr.id, array_agg( case when kv1.code_round_id = cr.id then kv1.option_id else null end ) as kv_values1, array_agg( case when kv2.code_round_id = cr_m.id then kv2.option_id else null end ) as kv_values2 from krypdos_coderound cr join krypdos_value kv1 on kv1.code_round_id = cr.id join krypdos_coderound cr_m on cr_m.object_id=cr.object_id and cr_m.content_type_id =cr.content_type_id join krypdos_value kv2 on kv2.code_round_id = cr_m.id WHERE cr.is_master= False AND cr_m.is_master= True AND cr.object_id=%s AND cr.content_type_id=%s GROUP BY cr.id ) t where t.id = cru.id """ % ( self.object_id, self.content_type.id) ) 

Tengo razones para creer que esto funciona bien. Sin embargo, esto ha llevado a un nuevo problema. Al intentar enviar, recibo un error de django que dice:

 IntegrityError at (some url): duplicate key value violates unique constraint "krypdos_value_pkey" 

He visto varias de las respuestas publicadas aquí y no he encontrado la solución a mi problema (aunque las preguntas relacionadas han sido una lectura interesante). Veo esto en mis registros, lo cual es interesante porque nunca llamo explícitamente a insertar- django debe manejarlo:

  STATEMENT: INSERT INTO "krypdos_value" ("code_round_id", "variable_id", "option_id", "confidence", "freetext") VALUES (1105935, 11, 55, NULL, E'') RETURNING "krypdos_value"."id" 

Sin embargo, al tratar de ejecutar eso se obtiene el error duplicado de la clave. El error real se arroja en el código a continuación.

  # Delete current coding CodeRound.objects.filter(object_id=o.id,content_type=object_type,is_master=True).delete() code_round = CodeRound(object_id=o.id,content_type=object_type,coded_by=request.user,comments=request.POST.get('_comments',None),is_master=True) code_round.save() for key in request.POST.keys(): if key[0] != '_' or key != 'csrfmiddlewaretoken': options = request.POST.getlist(key) for option in options: Value(code_round=code_round,variable_id=key,option_id=option,confidence=request.POST.get('_confidence_'+key, None)).save() #This is where it dies # Resave to set is_correct code_round.save() o.status = '3' o.save( 

He revisado las secuencias y tal parece que están en orden. En este punto, no estoy seguro de qué hacer, supongo que es algo al final de Django, pero no estoy seguro. ¡Cualquier comentario sería muy apreciado!

Esto me pasó a mí, resulta que necesitas volver a sincronizar tus campos de clave principal en Postgres. La clave es la statement de SQL:

 SELECT setval('tablename_id_seq', (SELECT MAX(id) FROM tablename)+1) 

Parece ser una diferencia de comportamiento conocida entre MySQL y SQLite (actualizan la próxima clave primaria disponible incluso cuando se inserta un objeto con un id. Explícito) backends, y otros backends como Postgres, Oracle, … (no lo hacen) .

Hay un boleto que describe el mismo problema . Aunque se cerró como no válido, proporciona una pista de que hay un comando de administración de Django para actualizar la siguiente clave disponible.

Para mostrar el SQL actualizando todos los siguientes identificadores para la aplicación MyApp :

 python manage.py sqlsequencereset MyApp 

Para ejecutar la instrucción, puede proporcionarla como entrada para el comando de administración de dbshell . Para bash, podrías escribir:

 python manage.py sqlsequencereset MyApp | python manage.py dbshell 

La ventaja de los comandos de administración es que abstrae el back-end subyacente de DB, por lo que funcionará incluso si más adelante migra a un back-end diferente.

Además de zapphods respuesta:

En mi caso, la indexación era realmente incorrecta, ya que había eliminado todas las migraciones, y la base de datos probablemente 10-15 veces cuando se desarrollaba, ya que no estaba en la etapa de migración de nada.

Estaba obteniendo un IntegrityError en finished_product_template_finishedproduct_pkey

Reindexe la tabla y reinicie el servidor de ejecución:

Estaba usando pgadmin3 y para cualquier índice que fuera incorrecto y arrojando errores clave duplicados navegué a las constraints y reindexé.

enter image description here

Y luego reindexado.

enter image description here

Si ha copiado manualmente las bases de datos, es posible que se encuentre con el problema que se describe aquí .

Tuve el mismo problema. Tenía una tabla existente en mi aplicación de “inventario” y quería agregar nuevos registros en django admin y obtuve estos mensajes:

El valor duplicado de la clave viola la restricción única “inventory_part_pkey” DETAIL: La clave (part_id) = (1) ya existe.

Como se mencionó anteriormente, ejecute el siguiente código para generar un comando SQL para restablecer los id-s:

 python manage.py sqlsequencereset inventory 

En mi caso, python manage.py sqlsequencereset MyApp | python manage.py dbshell python manage.py sqlsequencereset MyApp | python manage.py dbshell no funcionaba

  • Así que copié la statement SQL generada.
  • Luego abrí pgAdmin para postgreSQL y abrí mi db.
  • Haga clic en el ícono 6. (Ejecutar consultas SQL arbitrarias)
  • Copió la statement de lo que se generó.

En mi caso fue:

EMPEZAR; SELECT setval (pg_get_serial_sequence (‘”inventory_signup”‘, ‘id’), coalesce (max (“id”), 1), max (“id”) NO ES nulo) FROM “inventory_signup”; SELECT setval (pg_get_serial_sequence (‘”inventory_supplier”‘, ‘id’), coalesce (max (“id”), 1), max (“id”) NO ES nulo) FROM “inventory_supplier”; COMETER;

Se ejecutó con F5.

Esto arregló todas mis tablas y finalmente agregó nuevos registros al final, sin intentar agregarlo a id = 1.

Encontré este error porque estaba pasando argumentos adicionales al método de guardar de la manera incorrecta.

Para cualquiera que se encuentre con esto, intente forzar la ACTUALIZACIÓN con:

 instance_name.save(..., force_update=True) 

Si obtiene un error que no puede pasar force_insert y force_update al mismo tiempo, probablemente esté pasando algunos argumentos personalizados de la manera incorrecta, como yo lo hice.

La solución es que necesita resincronizar los campos de claves principales según lo informado por “Hacking Life”, que escribió un código SQL de ejemplo pero, como sugiere “Ad N”, es mejor ejecutar el comando sqlsequencereset Django para obtener el código SQL exacto que usted puede copiar y pasar o ejecutar con otro comando.

Como una mejora adicional de estas respuestas, le sugiero a usted y a otros lectores que no copien y peguen el código SQL, sino que ejecuten la consulta SQL generada por sqlsequencereset desde su código python de esta manera ( utilizando la base de datos predeterminada). )

 from django.core.management.color import no_style from django.db import connection from myapps.models import MyModel1, MyModel2 sequence_sql = connection.ops.sequence_reset_sql(no_style(), [MyModel1, MyModel2]) with connection.cursor() as cursor: for sql in sequence_sql: cursor.execute(sql) 

Probé este código con Python3.6 , Django 2.0 y PostgreSQL 10 .

Si desea restablecer el PK en todas sus tablas, como yo, puede utilizar la forma recomendada de PostgreSQL :

 SELECT 'SELECT SETVAL(' || quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname)) || ', COALESCE(MAX(' ||quote_ident(C.attname)|| '), 1) ) FROM ' || quote_ident(PGT.schemaname)|| '.'||quote_ident(T.relname)|| ';' FROM pg_class AS S, pg_depend AS D, pg_class AS T, pg_attribute AS C, pg_tables AS PGT WHERE S.relkind = 'S' AND S.oid = D.objid AND D.refobjid = T.oid AND D.refobjid = C.attrelid AND D.refobjsubid = C.attnum AND T.relname = PGT.tablename ORDER BY S.relname; 

Después de ejecutar esta consulta, deberá ejecutar los resultados de la consulta. Normalmente copio y pego en el Bloc de notas. Luego encuentro y reemplazo "SELECT with SELECT and ;" con ; . Copio y pego en pgAdmin III y ejecuto la consulta. Restablece todas las tablas en la base de datos. Más instrucciones “profesionales” se proporcionan en el enlace de arriba.