我正在将Django站点从MySQL迁移到PostgreSQL。数据量不是很大,所以我采用了一种非常简单的方法:我只是使用内置的Django serialize and deserialize例程来创建JSON记录,然后将它们加载到新实例中,遍历对象,并将每个保存到新数据库。
只需打个cup就可以很好地工作:加载所有记录后,在加载旧记录后尝试添加新数据时,我遇到了IntegrityError
。 MySQL自动递增ID字段的Postgres等效项是一个串行字段,但是当显式指定id值时,串行字段的内部计数器不会增加。结果,Postgres尝试从1开始使用记录编号-已经使用过-导致约束冲突。 (这是Django中的一个已知问题,标记为wontfix。)
有很多与此相关的问题和答案,但是似乎没有一个答案可以直接在Django上下文中解决该问题。 This answer给出了您需要运行以更新计数器的查询的示例,但我尝试避免在可能的情况下进行显式查询。我可以在保存之前简单地删除ID字段,然后让Postgres自己进行编号,但是在这种情况下,会损坏ForeignKey
引用。其他一切都很好!
如果Django提供一个执行此操作的例程以很好地处理任何边缘情况,那将是很好的。 (这不会修复该错误,但允许开发人员以一致且正确的方式解决它。)我们真的必须只使用原始查询来解决此问题吗?看来太野蛮了。
如果确实没有这样的例程,那么我将简单地执行以下操作,该操作直接运行上面链接的答案中建议的查询。但是在那种情况下,我很想听听这种方法的任何潜在问题,或者其他任何有关我可能做错事情的信息。例如,我是否应该只修改记录以使用UUID代替this suggests?
这是原始方法(已编辑,以反射(reflect)我实际完成的工作的简化版本)。它非常接近Pere Picornell的答案,但是他的表情对我来说更健壮。
table = model._meta.db_table
cur = connection.cursor()
cur.execute(
"SELECT setval('{}_id_seq', (SELECT max(id) FROM {}))".format(table, table)
)
最佳答案
关于辩论:我的情况是一次迁移,我的决定是在完成每个表的迁移后立即运行此功能,尽管您可以在怀疑完整性可能被破坏的任何时候调用它。
def synchronize_last_sequence(model):
# Postgresql aut-increments (called sequences) don't update the 'last_id' value if you manually specify an ID.
# This sets the last incremented number to the last id
sequence_name = model._meta.db_table+"_"+model._meta.pk.name+"_seq"
with connections['default'].cursor() as cursor:
cursor.execute(
"SELECT setval('" + sequence_name + "', (SELECT max(" + model._meta.pk.name + ") FROM " +
model._meta.db_table + "))"
)
print("Last auto-incremental number for sequence "+sequence_name+" synchronized.")
我是使用您在问题中提出的SQL查询来完成的。
查找您的帖子非常有用。谢谢!
它应与自定义PK一起使用,但不适用于多字段PK。
关于python - Django是否提供任何内置方式来更新PostgreSQL自动增量计数器?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53103154/