Postgresql SERIAL的工作方式不同吗?

zod*_*zod 18 mysql sql postgresql auto-increment

我有一个带有SERIAL ID的postgres表.

id (serial) name age
Run Code Online (Sandbox Code Playgroud)

插入通常发生在Web应用程序中.

我手动插入两条新记录,将id设置为max(id)+1****

在这两个插入后,当Web应用程序插入2个记录时,它会出现重复键错误.

仅2记录.之后一切正常.

问题是 - 为什么我的手动插入没有增加序列?

自动增量和串行是否不同?

我在这里错过了什么?MySQL或任何其他SQL有同样的问题吗?

mu *_*ort 47

当你创建一个serialbigserial列时,PostgreSQL实际上做了三件事:

  1. 创建一个intbigint列.
  2. 创建一个序列(由列拥有)以生成列的值.
  3. 将列的默认值设置为序列的默认值nextval().

当您在未指定serial列的情况下插入值(或者如果明确指定DEFAULT为其值)时,nextval将在序列上调用以:

  1. 返回列的下一个可用值.
  2. 增加序列的值.

如果手动为serial列提供非默认值,则序列将不会更新,并且nextval可以返回serial列已使用的值.因此,如果您执行此类操作,则必须通过调用nextvalsetval手动修复序列.

另外请记住,可以删除记录,因此serial可以预期列中的间隙,因此max(id) + 1即使没有并发问题,使用也不是一个好主意.

如果您正在使用serial或者bigserial,最好的办法是让PostgreSQL负责为您分配值,并假装它们是不透明的数字,恰好按照特定顺序出现:不要自己分配它们并且不要除了唯一性之外,我们假设一切.此经验法则适用于所有数据库IMO.


我不确定MySQL如何auto_increment与所有不同的数据库类型一起工作,但也许精细的手册会有所帮助.

  • 我的建议在于我的答案:将`serial`和`auto_increment`值留给数据库.不要乱用它们.如果你让数据库分配`serial`值,那么序列将被更新,一切都会好的; 如果手动分配值,则必须手动更新序列. (2认同)

Igo*_*nko 7

如果要将记录插入带有serial列的表中- 只需从查询中省略它 - 它将自动生成.

或者您可以使用以下内容插入其默认值:

insert into your_table(id, val)
values (default, '123');
Run Code Online (Sandbox Code Playgroud)

第三种选择是直接从串行序列中获取值:

insert into your_table(id, val)
values (nextval(pg_get_serial_sequence('your_table','id')), '123');
Run Code Online (Sandbox Code Playgroud)