the*_*lim 55 django postgresql database-integrity duplicates unique-constraint
关于我之前问过的一个问题,我正在跟进,我试图寻求从一个愚蠢/写得不好的mysql查询到postgresql的转换.我相信我成功了.无论如何,我正在使用手动从mysql数据库移动到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)
)
Run Code Online (Sandbox Code Playgroud)
我有理由相信这很有效.但是,这导致了一个新问题.在尝试提交时,我收到来自django的错误声明:
IntegrityError at (some url):
duplicate key value violates unique constraint "krypdos_value_pkey"
Run Code Online (Sandbox Code Playgroud)
我已经看过这里发布的几个回复,但我还没有找到解决问题的方法(虽然相关的问题已经有了一些有趣的阅读).我在日志中看到这个,这很有趣,因为我从未明确地调用insert-django必须处理它:
STATEMENT: INSERT INTO "krypdos_value" ("code_round_id", "variable_id", "option_id", "confidence", "freetext")
VALUES (1105935, 11, 55, NULL, E'')
RETURNING "krypdos_value"."id"
Run Code Online (Sandbox Code Playgroud)
但是,尝试运行会导致重复键错误.实际错误在下面的代码中引发.
# 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(
Run Code Online (Sandbox Code Playgroud)
我检查了序列等等,它们似乎是有序的.在这一点上,我不知道该怎么做 - 我认为这是django的结果,但我不确定.任何反馈将不胜感激!
Hac*_*ife 125
发生在我身上 - 事实证明你需要重新同步Postgres中的主键字段.关键是SQL语句:
SELECT setval('tablename_id_seq', (SELECT MAX(id) FROM tablename)+1)
Run Code Online (Sandbox Code Playgroud)
Ad *_*d N 21
它似乎是MySQL和SQLite之间已知的行为差异(即使在插入具有显式id的对象时,它们也会更新下一个可用的主键)后端,以及其他后端,如Postgres,Oracle,......(它们没有) .
有一张描述同一问题的票证.即使它被关闭为无效,它也提示有一个Django管理命令来更新下一个可用密钥.
要显示SQL更新应用程序MyApp的所有下一个ID :
python manage.py sqlsequencereset MyApp
Run Code Online (Sandbox Code Playgroud)
为了执行语句,您可以将其作为dbshell管理命令的输入提供.对于bash,您可以键入:
python manage.py sqlsequencereset MyApp | python manage.py dbshell
Run Code Online (Sandbox Code Playgroud)
管理命令的优点是抽象出底层数据库后端,因此即使稍后迁移到不同的后端也能工作.
我遇到过同样的问题.我的"库存"应用程序中有一个现有的表,我想在django admin中添加新记录,我收到了以下消息:
重复键值违反唯一约束"inventory_part_pkey"DETAIL:键(part_id)=(1)已存在.
如前所述,运行代码以生成一个SQL命令来重置id-s:
python manage.py sqlsequencereset inventory
Run Code Online (Sandbox Code Playgroud)
在我的情况下python manage.py sqlsequencereset inventory | python manage.py dbshell
没有工作
在我的情况下它是:
开始; 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"; 承诺;
用F5执行它.
这修复了我的所有表格,最后添加了新记录,最后不再尝试将其添加到id = 1.
除了zapphods答案:
在我的情况下,索引确实是错误的,因为我已经删除了所有迁移,并且数据库可能在开发时可能会有10-15次,因为我还没有进行任何迁移.
我得到了一个IntegrityError finished_product_template_finishedproduct_pkey
我正在使用pgadmin3并且对于任何索引都不正确并抛出重复键错误我导航到constraints并重新编制索引.

然后重新编制索引.

解决方案是您需要重新同步您的主键字段,如“Hacking Life”所报告的那样,他编写了一个示例 SQL 代码,但是,正如“Ad N”所建议的那样,最好运行 Django 命令sqlsequencereset以获取您可以使用的确切 SQL 代码复制并粘贴或使用另一个命令运行。
作为对这些答案的进一步改进,我建议您和其他读者不要“复制和粘贴 SQL 代码,但更安全地,以sqlsequencereset这种方式(使用默认数据库)执行从您的 Python 代码中生成的 SQL 查询” :
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)
Run Code Online (Sandbox Code Playgroud)
我用Python3.6、Django 2.0和PostgreSQL 10测试了这段代码。
如果你想像我一样重置所有表上的 PK,你可以使用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;
Run Code Online (Sandbox Code Playgroud)
运行此查询后,您将需要执行查询的结果。我通常复制并粘贴到记事本中。然后我找到并替换"SELECT为SELECT和;"。;我复制并粘贴到 pgAdmin III 中并运行查询。它重置数据库中的所有表。上面的链接提供了更多“专业”说明。
| 归档时间: |
|
| 查看次数: |
39745 次 |
| 最近记录: |