Как reset последовательность идентификаторов в таблицах PostgreSQL

Недавно я импортировал большое количество данных из старой базы данных в новую базу данных Postgresql в качестве основы для моделей на новом сайте Django.

Я использовал идентификаторы из старой базы данных (поскольку строки в разных таблицах относятся друг к другу), но они не все последовательно - часто встречаются большие пробелы.

Я заметил, что когда я добавляю новый объект через приложение Django, он использует идентификаторы, начинающиеся с 1, что не было проблемой, поскольку не было строк с очень маленькими идентификаторами.

Но как только он достигает первой строки устаревших данных, postgres явно жалуется:

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

Глядя на описания таблиц, я предполагаю, что мне нужно reset какую-то последовательность в каждой таблице:

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

Что мне нужно сделать для reset этой последовательности, чтобы новые строки были добавлены с идентификаторами, превышающими текущий максимальный ID?

Ответ 1

Запустите sqlsequencereset, и он выведет все команды reset, которые вам нужны.

Ответ 2

По предложению "Дмитрия Шевченко" вы можете запустить sqlsequencereset, чтобы решить вашу проблему.

или

Вы можете выполнить 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.0 и PostgreSQL 10.

Ответ 3

Вот короткий фрагмент для сброса всех последовательностей в 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())

Ответ 4

Команда PostgreSQL: ALTER SEQUENCE app_model_id_seq RESTART WITH 1

Ответ 5

select setval('django_comments_id_seq', 12345);

Ответ 7

на основе @Paolo Melchiorre я создал собственную команду управления, которая заполняет все модели из выбранных приложений.

from django.core.management.base import BaseCommand
from django.apps import apps
from django.core.management.color import no_style
from django.db import connection

class Command(BaseCommand):
    def handle(self, *args, **kwargs):
        self.stdout.write('Reset AutoFields ...')
        APPS = ['app1', 'app2']

        APPS = [apps.get_app_config(app) for app in apps]
        models = []
        for app in APPS:
            models.extend(list(app.get_models()))

        sequence_sql = connection.ops.sequence_reset_sql(no_style(), models)
        with connection.cursor() as cursor:
            for sql in sequence_sql:
                self.stdout.write(sql)
                cursor.execute(sql)
        self.stdout.write(self.style.SUCCESS('Reset AutoField complete.'))

протестировано с использованием python 3.7 и django 2.2.