Ich verfolge eine Frage, die ich zuvor gestellt habe und in der ich versucht habe, eine Konvertierung von einer doofen / schlecht geschriebenen MySQL-Abfrage zu Postgresql anzustreben. Ich glaube, das ist mir gelungen. Wie auch immer, ich verwende Daten, die manuell von einer MySQL-Datenbank in eine Postgres-Datenbank verschoben wurden. Ich verwende eine Abfrage, die so aussieht:
"""
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)
)
Ich habe Grund zu der Annahme, dass dies gut funktioniert. Dies hat jedoch zu einem neuen Problem geführt. Beim Versuch, etwas einzureichen, erhalte ich von django eine Fehlermeldung, die besagt:
IntegrityError at (some url):
duplicate key value violates unique constraint "krypdos_value_pkey"
Ich habe mir einige der hier veröffentlichten Antworten angesehen und die Lösung für mein Problem nicht ganz gefunden (obwohl die damit verbundenen Fragen für eine interessante Lektüre gesorgt haben). Ich sehe dies in meinen Protokollen, was interessant ist, weil ich insert nicht explizit aufrufe. Django muss damit umgehen:
STATEMENT: INSERT INTO "krypdos_value" ("code_round_id", "variable_id", "option_id", "confidence", "freetext")
VALUES (1105935, 11, 55, NULL, E'')
RETURNING "krypdos_value"."id"
Der Versuch, dies auszuführen, führt jedoch zu einem doppelten Schlüsselfehler. Der eigentliche Fehler wird im folgenden Code ausgegeben.
# 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(
Ich habe die Sequenzen und dergleichen überprüft und sie scheinen in Ordnung zu sein. An diesem Punkt bin ich mir nicht sicher, was ich tun soll - ich nehme an, es ist etwas am Ende von Django, aber ich bin mir nicht sicher. Jedes Feedback wäre sehr dankbar!
quelle
key[0] != '_' or key != 'csrfmiddlewaretoken'
gleichbedeutend mitnot (key[0] == '_' and key == 'csrfmiddlewaretoken')
. Es sollte leicht zu erkennen sein, dass die innere Bedingung niemals erfüllt ist, also äquivalent zunot (False)
oder mit anderen WortenTrue
. Aber warum sollte man sich dann mit dem beschäftigenif
?python manage.py sqlsequencereset <app> | python manage.py dbshell
Antworten:
Das ist mir passiert - es stellt sich heraus, dass Sie Ihre Primärschlüsselfelder in Postgres neu synchronisieren müssen. Der Schlüssel ist die SQL-Anweisung:
SELECT setval('tablename_id_seq', (SELECT MAX(id) FROM tablename)+1);
quelle
Es scheint ein bekannter Unterschied im Verhalten zwischen MySQL und SQLite (sie aktualisieren den nächsten verfügbaren Primärschlüssel, selbst wenn ein Objekt mit einer expliziten ID eingefügt wird) und anderen Backends wie Postgres, Oracle, ... zu sein (dies ist nicht der Fall). .
Es gibt ein Ticket, das das gleiche Problem beschreibt . Obwohl es als ungültig geschlossen wurde, gibt es einen Hinweis darauf, dass ein Django-Verwaltungsbefehl zum Aktualisieren des nächsten verfügbaren Schlüssels vorhanden ist.
So zeigen Sie die SQL-Aktualisierung aller nächsten IDs für die Anwendung MyApp an :
Damit die Anweisung ausgeführt werden kann, können Sie sie als Eingabe für den Befehl dbshell management bereitstellen . Für Bash können Sie Folgendes eingeben:
Der Vorteil der Verwaltungsbefehle besteht darin, dass das zugrunde liegende DB-Backend abstrahiert wird, sodass es auch bei einer späteren Migration auf ein anderes Backend funktioniert.
quelle
Ich hatte eine vorhandene Tabelle in meiner "Inventar" -App und wollte neue Datensätze in Django admin hinzufügen. Dabei wurde folgende Fehlermeldung angezeigt:
Wie bereits erwähnt, führe ich den folgenden Code aus, um den SQL-Befehl zum Zurücksetzen der IDs zu erhalten:
Verrohrung der
python manage.py sqlsequencereset inventory | python manage.py dbshell
zur Schale funktionierte nichthttps://www.pgadmin.org
für postgreSQL und öffnete meine DatenbankIn meinem Fall war der Raw-SQL-Befehl:
BEGIN; SELECT setval(pg_get_serial_sequence('"inventory_signup"','id'), coalesce(max("id"), 1), max("id") IS NOT null) FROM "inventory_signup"; SELECT setval(pg_get_serial_sequence('"inventory_supplier"','id'), coalesce(max("id"), 1), max("id") IS NOT null) FROM "inventory_supplier"; COMMIT;
Habe es mit F5 ausgeführt.
Das hat alles repariert.
quelle
Zusätzlich zu Zapphods Antwort:
In meinem Fall war die Indizierung in der Tat falsch, da ich alle Migrationen und die Datenbank bei der Entwicklung wahrscheinlich 10 bis 15 Mal gelöscht hatte, da ich mich nicht in der Phase der Migration befand.
Ich habe einen IntegrityError aktiviert
finished_product_template_finishedproduct_pkey
Indizieren Sie die Tabelle neu und starten Sie den Runserver neu:
Ich habe pgadmin3 verwendet und für jeden Index, der falsch war, und doppelte Schlüsselfehler
constraints
ausgelöst , habe ich zu und neu indiziert.Und dann neu indiziert.
quelle
Die Lösung besteht darin, dass Sie Ihre Primärschlüsselfelder erneut synchronisieren müssen, wie von "Hacking Life" gemeldet, der einen Beispiel-SQL-Code geschrieben hat. Wie von "Ad N" vorgeschlagen, ist es jedoch besser, den Befehl Django auszuführen
sqlsequencereset
, um den genauen SQL-Code zu erhalten, den Sie können kopieren und einfügen oder mit einem anderen Befehl ausführen.Als weitere Verbesserung dieser Antworten würde ich Ihnen und anderen Lesern empfehlen, den SQL-Code nicht zu kopieren und einzufügen, sondern die SQL-Abfrage, die von
sqlsequencereset
Ihrem Python-Code generiert wurde, auf diese Weise (unter Verwendung der Standarddatenbank ) sicherer auszuführen. ::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)
Ich habe diesen Code mit Python3.6 , Django 2.0 und PostgreSQL 10 getestet .
quelle
Wenn Sie die Datenbanken manuell kopiert haben, tritt möglicherweise das hier beschriebene Problem auf .
quelle
Wenn Sie die PK für alle Ihre Tabellen wie mich zurücksetzen möchten, können Sie die von PostgreSQL empfohlene Methode verwenden :
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;
Nach dem Ausführen dieser Abfrage müssen Sie die Ergebnisse der Abfrage ausführen. Normalerweise kopiere ich und füge es in den Editor ein. Dann finde und ersetze ich
"SELECT
mitSELECT
und;"
mit;
. Ich kopiere und füge es in pgAdmin III ein und führe die Abfrage aus. Es setzt alle Tabellen in der Datenbank zurück. Weitere "professionelle" Anweisungen finden Sie unter dem obigen Link.quelle
Ich bin auf diesen Fehler gestoßen, weil ich zusätzliche Argumente falsch an die Speichermethode übergeben habe.
Versuchen Sie für alle, die darauf stoßen, UPDATE zu erzwingen mit:
Wenn Sie einen Fehler erhalten, den Sie nicht übergeben können,
force_insert
undforce_update
gleichzeitig übergeben Sie wahrscheinlich einige benutzerdefinierte Argumente falsch, wie ich es getan habe.quelle
Sie müssen nur zu pgAdmin III gehen und dort Ihr Skript mit dem Namen der Tabelle ausführen:
SELECT setval('tablename_id_seq', (SELECT MAX(id) FROM tablename)+1);
quelle
Ich habe den gleichen Fehler wie beim OP erhalten.
Ich hatte einige Django-Modelle erstellt, eine Postgres-Tabelle basierend auf den Modellen erstellt und über Django Admin einige Zeilen zur Postgres-Tabelle hinzugefügt. Dann habe ich an einigen Spalten in den Modellen herumgespielt (Änderungen an ForeignKeys usw.), aber vergessen, die Änderungen zu migrieren.
Das Ausführen der Migrationsbefehle hat mein Problem gelöst, was angesichts der obigen SQL-Antworten sinnvoll ist.
Um zu sehen, welche Änderungen angewendet werden, ohne sie tatsächlich anzuwenden:
python manage.py makemigrations --dry-run --verbosity 3
Wenn Sie mit diesen Änderungen zufrieden sind, führen Sie Folgendes aus:
python manage.py makemigrations
Dann renne:
python manage.py migrate
quelle
Ich bekam ein ähnliches Problem und nichts schien zu funktionieren. Wenn Sie die Daten benötigen (dh beim Dump nicht ausschließen können), stellen Sie sicher, dass Sie alle post_save-Empfänger deaktiviert (kommentiert) haben. Ich denke, die Daten würden importiert, aber aufgrund dieser würde es wieder dasselbe Modell erstellen. Hat für mich gearbeitet.
quelle