IntegrityError重复键值违反唯一约束 - Django的/的PostgresInteg

2019-06-02 11:47发布

我在问候的跟进,我刚才问的问题中,我试图寻求一个愚蠢/写得不好的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)
  )

我有理由相信,这个效果很好。 然而,这导致了一个新的问题。 当试图提交,我从那个指出Django的一个错误:

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

我已经看了几个贴在这里的答复,我还没有完全找到了解决我的问题(虽然相关的问题都进行了一些有趣的阅读使)。 我看到这在我的日志,因为我从来没有显式调用嵌件的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"

但是,试图运行导致重复键错误。 实际的错误是在下面的代码抛出。

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

我检查了序列和这样的,他们似乎是为了。 在这一点上,我不知道该怎么做 - 我以为这是在Django的最终的东西,但我不知道。 任何反馈将不胜感激!

Answer 1:

这happend给我 - 原来你需要重新同步在Postgres的主键字段。 最关键的是SQL语句:

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


Answer 2:

这似乎是MySQL的和SQLite之间行为的已知差异后端(即使有明确的标识插入对象,当他们更新下一个可用的主键),以及其他后端像Postgres的,甲骨文,......(他们不这样做) 。

有描述了同样的问题一票 。 即使它被关闭无效,它提供了一个线索,有一个Django的管理命令来更新下一个可用的关键。

要显示SQL更新所有未来的IDS的应用程序MyApp的

python manage.py sqlsequencereset MyApp

为了有执行的语句,你可以将它作为其输入为dbshel​​l管理命令。 对于bash,您可以键入:

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

管理命令的优势是离抽象的底层数据库后端的,所以它会即使后来迁移到不同的后端工作。



Answer 3:

除了zapphods回答:

在我的情况下,索引确实是不正确的,因为我已经删除了所有迁移,数据库开发,因为我在任何迁移的阶段是没有可能时,10-15倍。

我正上IntegrityError finished_product_template_finishedproduct_pkey

重新索引表,并重新启动的runserver:

我用pgadmin3并取其指数是不正确的,丢我导航到重复键错误constraints和重建索引。

然后重建索引。



Answer 4:

我遇到过同样的问题。 我在“库存”应用程序有一个现有的表,我想在Django管理添加新的记录,我得到了这些消息:

重复键值违反唯一约束“inventory_part_pkey”详细信息:按键(PART_ID)=(1)已经存在。

正如前面提到的运行代码波纹管得到生成SQL命令重置ID-S:

python manage.py sqlsequencereset inventory

在我的情况python manage.py sqlsequencereset MyApp | python manage.py dbshell python manage.py sqlsequencereset MyApp | python manage.py dbshell不工作

  • 所以我复制生成的SQL语句。
  • 然后,对于PostgreSQL pgAdmin的打开,打开我的分贝。
  • 点击该图标6(执行任意SQL查询)
  • 复制产生什么声明。

在我的情况是:

开始; SELECT SETVAL(pg_get_serial_sequence( ' “inventory_signup”', 'ID'),聚结(最大( “ID”),1),最大( “ID”)不为空)FROM “inventory_signup”; SELECT SETVAL(pg_get_serial_sequence( ' “inventory_supplier”', 'ID'),聚结(最大( “ID”),1),最大( “ID”)不为空)FROM “inventory_supplier”; 承诺;

与F5执行它。

这个固定我所有的表,最后加入新的记录,到底要不要试图将其添加到ID = 1了。



Answer 5:

如果您手动复制数据库,您可能正在运行到这里所描述的问题 。



Answer 6:

解决的办法是,你需要重新同步您的主键字段由谁写了一个例子SQL代码,但是,通过“广告N”的建议是更好地运行Django的命令“黑客生活”报道sqlsequencereset得到确切的SQL代码,您可以复制和过去的或与另一命令来运行。

作为进一步的改进,这些问题的答案我会建议你和其他读者不要”复制和,但更安全地粘贴SQL代码,执行所产生的SQL查询sqlsequencereset在你的Python代码中以这种方式( 使用默认的数据库 ):

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)

我测试此代码与Python3.6,Django的2.0PostgreSQL 10。



Answer 7:

因为我经过额外的参数给保存方法错误的方式,我遇到了这个错误。

对于任何人谁遇到这种情形,请尝试强制更新:

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

如果你得到的是你不能传递一个错误force_insertforce_update在同一时间,你可能会传递一些自定义的参数错误的方式,像我一样。



Answer 8:

如果你想在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;

运行此查询后,您将需要执行查询的结果。 我通常复制并粘贴到记事本中。 然后我查找和替换"SELECTSELECT;"; 。 我复制并粘贴到的pgAdmin III和运行查询。 它重置所有数据库中的表。 在上面的链接提供了更多的“专业”的说明。



Answer 9:

我得到了同样的错误作为OP。

我创造了一些Django模型,创建一个Postgres表基础上的模型,并通过Django管理增加了一些行Postgres的表。 然后,我拨弄着在模型中的某些列(改变周围ForeignKeys等),但忘了迁移的变化。

运行迁移命令解决我的问题,这是有道理的给上面的SQL答案。

要看到什么样的变化将被应用,而无需实际应用它们:
python manage.py makemigrations --dry-run --verbosity 3

如果你喜欢这些变化,然后运行:
python manage.py makemigrations

然后运行:
python manage.py migrate



文章来源: IntegrityError duplicate key value violates unique constraint - django/postgres