postgres自动增量未在显式id插入上更新

jer*_*use 50 postgresql auto-increment

我在postgres中有下表:

CREATE TABLE "test" (
    "id" serial NOT NULL PRIMARY KEY,
    "value" text
)
Run Code Online (Sandbox Code Playgroud)

我正在做以下插入:

insert into test (id, value) values (1, 'alpha')
insert into test (id, value) values (2, 'beta')

insert into test (value) values ('gamma')
Run Code Online (Sandbox Code Playgroud)

在前2个插入中,我明确提到了id.但是,在这种情况下,表的自动增量指针不会更新.因此在第3个插入中我得到错误:

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

我从未在MyISAM和INNODB引擎中的Mysql中遇到过这个问题.显式与否,mysql总是根据最大行id更新自动增量指针.

postgres中这个问题的解决方法是什么?我需要它,因为我希望对我桌子中的某些ID进行更严格的控制.

更新: 我需要它,因为对于某些值我需要有一个固定的ID.对于其他新条目,我不介意创建新的条目.

我认为可以通过在我明确插入id时手动递增nextval指针来实现max(id) + 1.但我不知道该怎么做.

Mil*_*dev 89

这就是它应该如何工作 - next_val('test_id_seq')仅在系统需要该列的值并且您没有提供一个值时调用.如果您提供值,则不会执行此类调用,因此序列不会"更新".

您可以通过在上次插入后使用显式提供的值手动设置序列的值来解决此问题:

SELECT setval('test_id_seq', (SELECT MAX(id) from "test"));
Run Code Online (Sandbox Code Playgroud)

  • 奇怪的行为.我也来自MySQL.谢谢! (2认同)

ill*_*nan 6

在最新版本的 Django 中,文档中讨论了这个主题:

Django 使用 PostgreSQL 的SERIAL 数据类型来存储自动递增的主键。SERIAL 列填充有来自 跟踪下一个可用值的序列的值。手动为自动递增字段分配值不会更新字段的序列,这可能会在以后导致冲突。

参考: https : //docs.djangoproject.com/en/dev/ref/databases/#manually-specified-autoincrement-pk

还有管理命令manage.py sqlsequencereset app_label ...能够生成用于重置给定应用程序名称的序列的 SQL 语句

参考: https : //docs.djangoproject.com/en/dev/ref/django-admin/#django-admin-sqlsequencereset

例如,这些 SQL 语句是由manage.py sqlsequencereset my_app_in_my_project以下生成的:

BEGIN;
SELECT setval(pg_get_serial_sequence('"my_project_aaa"','id'), coalesce(max("id"), 1), max("id") IS NOT null) FROM "my_project_aaa";
SELECT setval(pg_get_serial_sequence('"my_project_bbb"','id'), coalesce(max("id"), 1), max("id") IS NOT null) FROM "my_project_bbb";
SELECT setval(pg_get_serial_sequence('"my_project_ccc"','id'), coalesce(max("id"), 1), max("id") IS NOT null) FROM "my_project_ccc";
COMMIT;
Run Code Online (Sandbox Code Playgroud)