Последовательность PostgreSQL сбрасывается?

Мои веб-приложения Django регулярно выдают ошибки SQL в таблицах M2M.

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

Приложение выполняет обычные запросы SQL, такие как:

INSERT INTO "myapp_project" ("name") VALUES ('test1') RETURNING "myapp_project"."id"'

которые вызывают такие ошибки, как:

IntegrityError: duplicate key value violates unique constraint "myapp_project_pkey"
DETAIL:  Key (id)=(29) already exists.

Затем оказывается, что myapp_project_id_seq указывает на старый идентификационный номер:

select currval('myapp_project_id_seq')
29

Который затем можно сбросить, используя:

select setval('myapp_project_id_seq', (select max(id) from myapp_project))

Однако я не могу объяснить, почему это происходит. Обычно это происходит на таблицах M2M в Django. В данном случае это обычная таблица с доступом только для администратора. Может ли кто-нибудь просветить меня по этому поводу?


person vdboor    schedule 28.08.2014    source источник
comment
Вы почти наверняка где-то вставляете идентификатор вручную. Где я не мог сказать, но это то, где вы должны начать искать.   -  person Richard Huxton    schedule 28.08.2014
comment
Интересно. @RichardHuxton: вставка идентификатора также приводит к сбросу последовательности? Или это будет означать, что это было испорчено раньше?   -  person vdboor    schedule 29.08.2014
comment
нет, что происходит, вы вставляете строки 1,2,3, используя последовательность, а затем делаете 4,5 вручную. Следующий автоматически сгенерированный идентификатор будет 4, потому что он не знает, что вы сделали. Это дает ошибку.   -  person Richard Huxton    schedule 29.08.2014


Ответы (1)


Обычно это происходит, когда вы (или кто-то другой) иногда записываете значения в id явно, вместо того, чтобы получать значения из последовательности (по умолчанию или с nextval()).

В вашем коде ремонта не хватает пары скобок.

SELECT setval('myapp_project_id_seq', (SELECT max(id) FROM myapp_project));

Это немного короче и дешевле, делая то же самое:

SELECT setval('myapp_project_id_seq', max(id)) FROM myapp_project;
person Erwin Brandstetter    schedule 28.08.2014