如何重置PostgreSQL表上的ID序列

Phi*_*ord 21 django postgresql

我最近将旧数据库中的大量数据导入到新的Postgresql数据库中,作为新Django站点中模型的基础.

我使用旧数据库中的ID(因为各个表中的行互相引用),但它们并非都是顺序的 - 通常存在很大的差距.

我注意到,当我通过Django应用程序添加一个新对象时,它一直使用从1开始的ID,这对于没有ID非常低的行来说并不是问题.

但是一旦它到达第一行遗留数据,那么postgres显然会抱怨:

ERROR:  duplicate key value violates unique constraint "django_comments_pkey"
DETAIL:  Key (id)=(25) already exists.
Run Code Online (Sandbox Code Playgroud)

查看表格描述我猜我需要在每个表格上重置某种序列:

                                      Table "public.django_comments"
     Column      |           Type           |                          Modifiers                           
-----------------+--------------------------+--------------------------------------------------------------
 id              | integer                  | not null default nextval('django_comments_id_seq'::regclass)
...
Run Code Online (Sandbox Code Playgroud)

我需要做什么来重置该序列,以便添加ID高于当前最大ID的新行?

Dmi*_*nko 45

运行sqlsequencereset,它将打印您需要的所有重置命令.

  • 你可以这样做:`python manage.py sqlsequencereset app_name | python manage.py dbshel​​l`它将自动执行 (9认同)
  • 我从来没有想过会有一种特定于Django的方式来获取我追求的东西!谢谢德米特里. (5认同)

Pao*_*rre 10

按照“德米特里·舍甫琴科”的建议,您可以运行sqlsequencereset以解决您的问题。

要么

您可以通过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.6Django 2.0PostgreSQL 10测试了此代码。


Dan*_*ley 7

这是一个简短的片段,用于重置Django 1.9+中的所有序列(基于http://djangosnippets.org/snippets/2774/)并与Python 3兼容:

import os
from io import StringIO

os.environ['DJANGO_COLORS'] = 'nocolor'

from django.core.management import call_command
from django.apps import apps
from django.db import connection

commands = StringIO()
cursor = connection.cursor()

for app in apps.get_app_configs():
    label = app.label
    call_command('sqlsequencereset', label, stdout=commands)

cursor.execute(commands.getvalue())
Run Code Online (Sandbox Code Playgroud)

  • 如果您想知道为什么会出现 SQL 语法错误,请检查代码中是否有 os.environ['DJANGO_COLORS'] = 'nocolor' 。这将在 sqlsequencereset 的输出中转义 unicode 颜色指令 (2认同)

Mic*_*rts 5

所以在我看来,最快、最简单、最“Django”的方法是使用以下管理命令:

python manage.py sqlsequencereset app_name
Run Code Online (Sandbox Code Playgroud)

在此之后,您将得到如下信息:

BEGIN;
SELECT setval(pg_get_serial_sequence('"measurements_quantity"','id'), coalesce(max("id"), 1), max("id") IS NOT null) FROM "measurements.Quantities";
SELECT setval(pg_get_serial_sequence('"measurements.Prefixes"','id'), coalesce(max("id"), 1), max("id") IS NOT null) FROM "measurements.Prefixes";
COMMIT;
Run Code Online (Sandbox Code Playgroud)

下一步是在python manage.py dbshell管理命令中运行它,因此运行它,然后您将在终端中看到交互数据库外壳:

psql (11.7 (Debian 11.7-0+deb10u1), server 11.5 (Debian 11.5-1.pgdg90+1))
Type "help" for help.

postgres=# BEGIN;
BEGIN
postgres=# SELECT setval(pg_get_serial_sequence('"measurements.Quantities"','id'), coalesce(max("id"), 1), max("id") IS NOT null) FROM "measurements.Quantities";
 setval 
--------
      1
(1 row)

postgres=# SELECT setval(pg_get_serial_sequence('"measurements.Prefixes"','id'), coalesce(max("id"), 1), max("id") IS NOT null) FROM "measurements.Prefixes";
 setval 
--------
      1
(1 row)

postgres=# COMMIT;
COMMIT
postgres=# exit
Run Code Online (Sandbox Code Playgroud)

就那么简单。该python manage.py sqlsequencereset app_name命令将为您提供需要运行的 SQL,您可以在dbshell.

无需编写您自己的自定义 SQL 或自定义代码,它将以正确的格式和选择的数据库引擎为您提供所需的内容。