IntegrityError duplicate key value narusza unikalne ograniczenie-django / postgres
Podążam za pytaniem , które zadałem wcześniej, w którym Szukałem konwersji z głupiego/źle napisanego zapytania mysql do postgresql. Wierzę, że mi się to udało. Tak czy inaczej, używam danych, które zostały ręcznie przeniesione z bazy danych mysql do bazy danych postgres. Używam zapytania, które wygląda tak:
"""
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)
)
Mam powody sądzić, że to działa dobrze. Doprowadziło to jednak do nowej kwestii. Podczas próby przesłania otrzymuję błąd z django stwierdza się:
IntegrityError at (some url):
duplicate key value violates unique constraint "krypdos_value_pkey"
Przejrzałem kilka odpowiedzi zamieszczonych tutaj i nie do końca znalazłem rozwiązanie mojego problemu (chociaż powiązane pytania sprawiły, że można je ciekawie przeczytać). Widzę to w moich logach, co jest ciekawe, ponieważ nigdy jawnie nie wywołuję insert-django musi to obsłużyć:
STATEMENT: INSERT INTO "krypdos_value" ("code_round_id", "variable_id", "option_id", "confidence", "freetext")
VALUES (1105935, 11, 55, NULL, E'')
RETURNING "krypdos_value"."id"
Jednak próba uruchomienia powoduje błąd duplikatu klucza. Rzeczywisty błąd jest wyrzucany w kodzie poniżej.
# 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(
Sprawdziłem sekwencje i takie i wydają się być w porządku. W tym momencie Nie jestem pewien, co robić - zakładam, że to coś na końcu django, ale nie jestem pewien. Wszelkie opinie będą mile widziane!
8 answers
To mi się przydarzyło-okazuje się, że musisz ponownie zsynchronizować swoje główne pola kluczowe w Postgres. Kluczem jest polecenie SQL:
SELECT setval('tablename_id_seq', (SELECT MAX(id) FROM tablename)+1)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-06 05:03:25
Wydaje się, że jest to znana różnica między backendami MySQL i SQLite (aktualizują następny dostępny klucz podstawowy nawet podczas wstawiania obiektu o jawnym id), a innymi backendami, takimi jak Postgres, Oracle,... (nie mają).
Istnieje bilet opisujący ten sam problem . Nawet jeśli został zamknięty jako nieprawidłowy, dostarcza podpowiedzi, że istnieje polecenie zarządzania Django, aby zaktualizować następny dostępny klucz.
Aby wyświetlić aktualizację SQL wszystkie następne ID dla aplikacji MyApp :
python manage.py sqlsequencereset MyApp
Aby polecenie zostało wykonane, możesz podać je jako dane wejściowe dla polecenia zarządzającego dbshell . Dla Basha można wpisać:
python manage.py sqlsequencereset MyApp | python manage.py dbshell
Zaletą poleceń zarządzania jest to, że pobiera bazowy backend DB, więc będzie działał nawet w przypadku późniejszej migracji do innego backendu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-17 14:24:40
Oprócz zapphods odpowiedź:
W moim przypadku indeksowanie było rzeczywiście błędne, ponieważ usunąłem wszystkie Migracje, a baza danych prawdopodobnie 10-15 razy podczas tworzenia, ponieważ nie byłem na etapie migracji czegokolwiek.
Dostałem IntegrityError na finished_product_template_finishedproduct_pkey
Reindex tabeli i restart runserver:
Używałem pgadmin3 i dla tego, który indeks był niepoprawny i rzucał duplikaty błędów klawiszy nawigowałem do constraints
i renifer.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-21 21:42:14
Jeśli ręcznie skopiowałeś bazy danych, możesz napotkać problem opisany tutaj .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-18 20:00:04
Miałem ten sam problem. Miałem istniejącą tabelę w mojej aplikacji "inventory" i chciałem dodać nowe rekordy w django admin i dostałem te wiadomości:
Zduplikowana wartość klucza narusza unikalne ograniczenie " inventory_part_pkey" DETAIL: Key (part_id) = (1) już istnieje.
Jak wspomniano wcześniej Uruchom poniższy kod, aby wygenerować polecenie SQL, aby zresetować id-s:
python manage.py sqlsequencereset inventory
W moim przypadku python manage.py sqlsequencereset MyApp | python manage.py dbshell
nie działa
- więc skopiowałem wygenerowany SQL oświadczenie.
- następnie otworzyłem pgAdmin dla postgreSQL i otworzyłem mój db.
- Kliknij na 6. icon (wykonaj dowolne zapytania SQL)
- skopiował to, co zostało wygenerowane.
W moim przypadku było:
BEGIN; Wybierz setval(pg_get_serial_sequence('"inventory_signup"','id'), coalesce(max("id"), 1), max("id") nie jest null) z "inventory_signup"; SELECT setval(pg_get_serial_sequence('"inventory_supplier"','id'), coalesce (max ("id"), 1), max ("id") nie jest null) z "inventory_supplier"; COMMIT;
Wykonałem z F5.
To poprawiło wszystkie moje tabele i ostatecznie dodało nowe rekordy do końca, nie próbując już dodawać go do id = 1.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-22 15:45:50
Rozwiązaniem jest to, że musisz ponownie zsynchronizować swoje podstawowe pola klucza, jak donosi "Hacking Life", który napisał przykładowy kod SQL, ale, jak sugeruje "Ad N", Lepiej jest uruchomić polecenie Django sqlsequencereset
, Aby uzyskać dokładny kod SQL, który możesz skopiować i przekazać lub uruchomić za pomocą innego polecenia.
Jako dalsze ulepszenie tych odpowiedzi sugerowałbym Tobie i innym czytelnikom, aby nie kopiować i wklejać kodu SQL, ale bezpieczniej wykonać zapytanie SQL wygenerowane przez sqlsequencereset
z wewnątrz twojego kod Pythona w ten sposób (używając domyślnej bazy danych):
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)
Testowałem ten kod z Python3.6, Django 2.0 i PostgreSQL 10.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-12 11:34:21
Napotkałem ten błąd, ponieważ przekazywałem dodatkowe argumenty do metody save w niewłaściwy sposób.
Dla każdego, kto napotka to, spróbuj wymusić UPDATE z:
instance_name.save(..., force_update=True)
Jeśli pojawi się błąd, którego nie możesz przekazać force_insert
i force_update
w tym samym czasie, prawdopodobnie przekazujesz niektóre niestandardowe argumenty w niewłaściwy sposób, tak jak ja.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-02 13:01:14
Jeśli chcesz zresetować PK na wszystkich swoich stołach, tak jak ja, możesz użyć PostgreSQL recommended way :
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;
Po uruchomieniu tego zapytania, będziesz musiał wykonać wyniki zapytania. Zazwyczaj kopiuję i wklejam do Notatnika. Następnie znajduję i zamieniam "SELECT
na SELECT
i ;"
na ;
. Kopiuję i wklejam do pgAdmin III i uruchamiam zapytanie. Resetuje wszystkie tabele w bazie danych. Więcej "profesjonalnych" instrukcji znajduje się pod linkiem powyżej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-14 17:56:30