40

Sto seguendo un question that I asked earlier in cui ho cercato di cercare una conversione da una query mysql goofy/mal scritta a postgresql. Credo di esserci riuscito. Ad ogni modo, sto usando i dati che sono stati spostati manualmente da un database mysql a un database postgres. Sto utilizzando una query che assomiglia così:IntegrityErrore valore chiave duplicato viola un vincolo univoco - 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) 
) 

Ho ragione di credere che questo funziona bene. Tuttavia, questo ha portato a un nuovo problema. Quando si cerca di presentare, ottengo un errore da django che afferma:

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

Ho guardato alcune delle risposte pubblicate su questo sito e non ho abbastanza trovato la soluzione al mio problema (anche se le questioni connesse ho fatto per alcune letture interessanti). Vedo questo nei miei ceppi, il che è interessante perché non ho mai chiamare esplicitamente inserire: Django devono gestire la cosa:

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

Tuttavia, il tentativo di eseguire che genera l'errore chiave duplicata. L'errore effettivo viene generato nel codice qui sotto.

# 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(

Ho controllato le sequenze e tali e sembrano essere in ordine. A questo punto non sono sicuro di cosa fare- presumo che sia qualcosa alla fine del django ma non ne sono sicuro. Qualsiasi feedback sarebbe molto apprezzato!

+1

Un conto a parte: secondo le leggi di De Morgan, la tua condizione 'chiave [0]! = '_' O chiave!= 'csrfmiddlewaretoken'' è equivalente a 'not (chiave [0] ==' _ 'e tasto ==' csrfmiddlewaretoken ')'. Dovrebbe essere facile vedere che la condizione interna non è mai soddisfatta, quindi è equivalente a 'not (False)', o in altre parole 'True'. Ma allora perché preoccuparsi del 'se'? –

+0

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

+0

Questa risposta precedente fornisce maggiori dettagli e luce sull'argomento: http://stackoverflow.com/questions/244243/how-to-reset-postgres-primary-key-sequence-when-it-falls -out-of-sync – RedSands

risposta

94

Questo è successo a me - risulta che è necessario risincronizzare i campi chiave primaria in Postgres. La chiave è l'istruzione SQL:

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

Ecco fatto! Pensavo di aver risolto il problema ma risulta che ho azzerato il valore sbagliato. –

+1

Conosco un sacco di persone che hanno avuto questo problema - Sono contento che tu l'abbia risolto! –

+0

stavo per chiederlo a @HackingLife se sapessi di più sul perché questo accade ... risulta per noi, è perché stavamo sincronizzando tutti i dati da un database diverso copiandolo direttamente (che è stato menzionato da zaphod nella sua risposta). Quando abbiamo smesso di farlo e abbiamo iniziato a utilizzare direttamente il database principale, la sequenza della chiave primaria non era stata incrementata quando è stato aggiunto un nuovo modello, producendo questo errore. – AJP

2

Ho riscontrato questo errore perché stavo passando argomenti extra al metodo di salvataggio nel modo sbagliato.

Per chi incontra questo, provare a forzare UPDATE con:

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

Se si ottiene un errore che non è possibile passare force_insert e force_update allo stesso tempo, probabilmente stai passando alcuni argomenti personalizzati nel modo sbagliato , come ho fatto io.

+0

Questa è una bella soluzione nel django. Dalla shell basta importare la classe del modello (se non si utilizza shell_plus) e quindi fare MyModelClass.objects.first(). Save (force_update = True) –

5

Oltre a zapphods risposta:

Nel mio caso l'indicizzazione era davvero corretto, dal momento che avevo cancellato tutte le migrazioni, e il database probabilmente 10-15 volte in cui in via di sviluppo non ero nella fase di migrazione nulla.

mi è stato sempre un IntegrityError su finished_product_template_finishedproduct_pkey

Reindicizza tavolo e riavviare runserver:

stavo usando pgadmin3 e per qualsiasi indice non era corretta e gettando duplicare gli errori chiave che ho navigato al constraints e indicizzato.

enter image description here

E poi indicizzato.

enter image description here

11

Sembra essere una differenza noto di comportamento tra il MySQL e SQLite (aggiornano la chiave primaria disponibile successivo anche quando si inserisce un oggetto con un id esplicito) backend, e altri backend come Postgres, Oracle , ... (loro non).

There is a ticket describing the same issue. Anche se è stato chiuso come non valido, fornisce un suggerimento che esiste un comando di gestione Django per aggiornare la prossima chiave disponibile.

Per visualizzare l'SQL aggiornare tutti i futuri ID per l'applicazione MiaApp:

python manage.py sqlsequencereset MyApp 

Al fine di avere l'istruzione eseguita, è possibile fornire come input per il comando dbshell gestione. Per bash, è possibile digitare:

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

Il vantaggio della gestione comandi è che astrae il sottostante DB backend, in modo da funzionare anche se successivamente la migrazione a un backend diverso.

1

Ho avuto lo stesso problema. Ho avuto una tabella esistente nella mia app "inventario" e ho voluto aggiungere nuovi record in Django admin e ho avuto questi messaggi:

Duplicate valore chiave violano vincolo unico "inventory_part_pkey" DETTAGLIO: Tasto (part_id) = (1) esiste già.

Come accennato prima eseguire il codice qui sotto per ottenere generare un comando SQL per reimpostare l'id-s:

python manage.py sqlsequencereset inventory 

Nel mio caso python manage.py sqlsequencereset MyApp | python manage.py dbshell non funzionava

  • Così ho copiato l'istruzione SQL generata.
  • Quindi ha aperto pgAdmin per postgreSQL e ha aperto il mio db.
  • Clic sull'icona 6. (Esegui query SQL arbitrarie)
  • Copiato l'istruzione che cosa è stato generato.

Nel mio caso era:

BEGIN; SELECT setval (pg_get_serial_sequence ('"inventory_signup"', 'id'), coalesce (max ("id"), 1), max ("id") NON è null) FROM "inventory_signup"; SELECT setval (pg_get_serial_sequence ('"inventory_supplier"', 'id'), coalesce (max ("id"), 1), max ("id") NON è null) FROM "inventory_supplier"; COMMIT;

Eseguito con F5.

Questo ha corretto tutti i miei tavoli e infine aggiunto nuovi record fino alla fine, non cercando più di aggiungerlo a id = 1.

+0

Questa risposta mi ha salvato la giornata! – Gambit2007