40

Estoy siguiendo con respecto a un question that I asked earlier en el que busqué buscar 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í:IntegrityError valor clave duplicado viola la restricción única - django/postgres

""" 
    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. Cuando se trata de presentar, me sale un error de Django que dice:

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

He mirado en varias de las respuestas publicadas en aquí y no es haber encontrado la solución a mi problema (aunque las cuestiones relacionadas han hecho algunas lecturas interesantes). Veo esto en mis registros, lo cual es interesante porque nunca llamar explícitamente Insert- Django deben 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, tratando de correr que los resultados en el error de clave duplicada. 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 comprobado 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!

+1

Un aparte: según las leyes de De Morgan, su condición 'tecla [0]! = '_' O clave!= 'csrfmiddlewaretoken'' es equivalente a 'not (clave [0] ==' _ 'y clave ==' csrfmiddlewaretoken ')'. Debería ser fácil ver que la condición interna nunca está satisfecha, por lo que es equivalente a 'no (Falso)', o en otras palabras, 'Verdadero '. Pero entonces ¿por qué molestarse con el 'si'? –

+0

'python manage.py sqlsequencereset | python manage.py dbshell' – Medorator

+0

Esta respuesta anterior brinda más detalles y aclara el tema: http://stackoverflow.com/questions/244243/how-toetrespost-postgres-primary-key-sequence-when-it-falls -out-of-sync – RedSands

Respuesta

94

Me pasó esto, resulta que necesita volver a sincronizar los campos de clave principal en Postgres. La clave es la declaración de SQL:

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

¡Eso fue todo! Pensé que había abordado ese problema, pero resulta que reinicié el valor incorrecto. –

+1

Conozco a un grupo de personas que han tenido este problema. ¡Me alegra que lo hayas resuelto! –

+0

Estaba a punto de preguntarle a @HackingLife si sabía más acerca de por qué sucede esto ... resultó para nosotros, fue porque estábamos sincronizando todos los datos de una base de datos diferente copiándolo directamente (lo cual fue mencionado zaphod en su respuesta) Cuando dejamos de hacer eso y empezamos a usar la base de datos principal directamente, la secuencia de la clave principal no se había incrementado cuando se agregó un nuevo modelo, lo que produjo este error. – AJP

2

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

Para cualquier persona que se encuentra con esto, tratar de forzar UPDATE con:

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

Si se produce un error que no se puede pasar force_insert y force_update, al mismo tiempo, es probable que pasar algunos argumentos personalizados por el camino equivocado , como yo lo hice.

+0

Esta es una buena solución dentro de django. Desde el shell simplemente importa tu clase de modelo (si no estás usando shell_plus) y luego haz MyModelClass.objects.first(). Save (force_update = True) –

5

Además de zapphods respuesta:

En mi caso fue la indexación de hecho incorrecta, ya que me había borrado todas las migraciones, y la base de datos probablemente a 10-15 veces la hora de desarrollar ya que no estaba en la etapa de la migración cualquier cosa.

que estaba recibiendo un IntegrityError en finished_product_template_finishedproduct_pkey

indexar la tabla de ejecución del servidor y reinicie:

que estaba usando pgadmin3 y para cualquier índice era incorrecta y tirar duplicar los errores clave que navegó al constraints y re-indexada.

enter image description here

Y luego re-indexada.

enter image description here

11

Parece haber una diferencia conocida de comportamiento entre el MySQL y SQLite (que actualicen la siguiente clave primaria disponible incluso cuando la inserción de un objeto con un identificador explícito) backends y otros backends como PostgreSQL, Oracle , ... (ellos no).

There is a ticket describing the same issue. 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 visualizar el SQL actualizar todos los siguientes identificadores de la aplicación MiApl:

python manage.py sqlsequencereset MyApp 

el fin de tener la sentencia ejecutada, puede proporcionarlo como entrada para el comando dbshell gestión. Para bash, podría escribir:

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

La ventaja de la gestión de los comandos es que los resúmenes de distancia de la base de datos subyacente de back-end, por lo que trabajará incluso si después de migrar a un motor diferente.

1

Tuve el mismo problema. Tenía una tabla existente en mi aplicación "inventario" y que quería añadir nuevos registros en la administración de Django y me dieron estos mensajes:

valor de clave duplicado viola restricción única "inventory_part_pkey" DETALLE: Clave (part_id) = (1) ya existe.

Como se ha mencionado antes ejecutar el código de abajo para conseguir generar un comando SQL para restablecer el id-s:

python manage.py sqlsequencereset inventory 

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

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

En mi caso fue:

COMENZAR; SELECCIONAR setval (pg_get_serial_sequence ('"inventory_signup"', 'id'), coalesce (max ("id"), 1), max ("id") NO ES nulo) FROM "inventory_signup"; SELECCIONAR setval (pg_get_serial_sequence ('"inventory_supplier"', 'id'), coalesce (max ("id"), 1), max ("id") NO ES nulo) FROM "inventory_supplier"; COMPROMISO;

Se ejecutó con F5.

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

+0

¡Esta respuesta me salvó la vida! – Gambit2007

Cuestiones relacionadas