完整性错误:违反唯一约束条件的重复键值 - Django/PostgreSQL

92

关于我之前提出的问题,我在寻求将一个笨拙/写得很差的mysql查询转换为postgresql。我相信我已经成功了。无论如何,我正在使用手动从mysql数据库移动到postgresql数据库的数据。我正在使用以下查询:

  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"

我看了这里发布的几个回答,但还没有找到解决我的问题的方法(虽然相关问题很有趣)。我在日志中看到了这个,这很有趣,因为我从来没有显式地调用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"

然而,尝试运行该代码会导致重复键错误。实际的错误信息在下面的代码中抛出。

# 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端的问题,但我不确定。非常感谢任何反馈!


2
顺便提一下:根据德摩根定律,您的条件key[0] != '_' or key != 'csrfmiddlewaretoken'等同于not (key[0] == '_' and key == 'csrfmiddlewaretoken')。很容易看出内部条件永远不会被满足,因此它等同于not (False),换句话说就是True。那么为什么还要使用if呢? - Jonas Kölker
python manage.py sqlsequencereset <app> | python manage.py dbshell - user
此前的回答提供了更详细的信息和解释:https://dev59.com/eXVC5IYBdhLWcg3wlyQo - RedSands
14个回答

0

我遇到了与OP相同的错误。

我创建了一些Django模型,基于这些模型创建了一个Postgres表,并通过Django Admin向Postgres表中添加了一些行。然后我调整了一些模型中的列(更改ForeignKeys等),但忘记了迁移更改。

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

要查看将应用哪些更改,而不实际应用它们:
python manage.py makemigrations --dry-run --verbosity 3

如果您对这些更改满意,请运行:
python manage.py makemigrations

然后运行:
python manage.py migrate


0

根据Paolo Melchiorre的回答,我编写了一个代码块作为函数,在任何.save()之前调用该函数

from django.db import connection
def setSqlCursor(db_table):
    sql = """SELECT pg_catalog.setval(pg_get_serial_sequence('"""+db_table+"""', 'id'), MAX(id)) FROM """+db_table+""";"""
    with connection.cursor() as cursor:
        cursor.execute(sql)

0

你只需要打开pgAdmin III,然后在那里执行你的脚本并输入表名:

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

这有什么不同于被接受的答案吗? - Afsan Abdulali Gujarati

0

这是正确的语句。通常,当我们插入带有id字段的行时会发生这种情况。

SELECT setval('tablename_id_seq', (SELECT MAX(id) FROM tablename));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接