问题

在我日常使用 PostgreSQL 数据库过程中,会遇到一个问题:我在重新创建一个数据库表时,往往会导入已有的数据,这样会导致新增表数据时,由于 id 采用了自增,会从1开始生成,然后由于已有数据的缘故, 所以会导致 id 重复报错。

解决

查看了 stackoverflow 的一些回答,发现了一个解决方案:采用 ALTER SEQUENCE 语句进行修改。

ALTER SEQUENCE

ALTER SEQUENCE — 更改序列生成器的定义

语法:

ALTER SEQUENCE [ IF EXISTS ] name
    [ AS data_type ]
    [ INCREMENT [ BY ] increment ]
    [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
    [ START [ WITH ] start ]
    [ RESTART [ [ WITH ] restart ] ]
    [ CACHE cache ] [ [ NO ] CYCLE ]
    [ OWNED BY { table_name.column_name | NONE } ]
ALTER SEQUENCE [ IF EXISTS ] name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER SEQUENCE [ IF EXISTS ] name RENAME TO new_name
ALTER SEQUENCE [ IF EXISTS ] name SET SCHEMA new_schema

参数:

name
要变更的序列名称。

IF EXISTS
如果序列不存在,不抛出错误。(这种情况会发出通知)

data_type
可选的子句AS data_type改变序列的数据类型。有效的类型是smallint、integer和bigint。

改变数据类型会自动改变序列的最小值和最大值,前提是以前的最小值和最大值是旧数据类型的最小值或最大值(换句话说,如果序列是用NO MINVALUE或NO MAXVALUE创建的,隐含地或明确地)。否则,最小值和最大值将被保留,除非作为同一命令的一部分给出新的值。如果最小值和最大值不适合新的数据类型,将产生一个错误。

increment
子句INCREMENT BY increment是可选的。一个正值将形成升序,一个负值将形成降序。如果没有指定,将保持旧的增量值。

minvalue
NO MINVALUE
可选的子句MINVALUE minvalue决定了一个序列可以产生的最小值。如果没有指定MINVALUE,将分别使用默认的1和升序和降序的数据类型的最小值。如果两个选项都没有指定,将保持当前的最小值。

maxvalue
NO MAXVALUE
可选的子句MAXVALUE maxvalue决定了序列的最大值。如果没有指定MAXVALUE,将分别使用数据类型的最大值和升序和降序的-1的默认值。如果两个选项都没有指定,将保持当前的最大值。

start
可选的子句START WITH start改变序列的记录起始值。这对当前的序列值没有影响;它只是设置了未来ALTER SEQUENCE RESTART命令将使用的值。

restart
可选子句RESTART [ WITH restart ] 改变序列的当前值。这与调用is_called = false的setval函数类似:指定的值将由下次调用nextval返回。写入没有重启值的RESTART等同于提供由CREATE SEQUENCE记录的或由ALTER SEQUENCE START WITH最后设置的起始值。

与setval调用相反,序列上的RESTART操作是事务性的,并阻止并发的事务从同一序列中获取数字。如果这不是想要的操作模式,应该使用setval。

cache
条款CACHE缓存使序列号被预先分配并存储在内存中,以加快访问速度。最小值为1(一次只能生成一个值,即没有缓存)。如果没有指定,将保持旧的缓存值。

CYCLE
可选的CYCLE关键词可以用来使序列在升序或降序分别达到最大值或最小值时进行环绕。如果达到极限,下一个生成的数字将分别是最小值或最大值。

NO CYCLE
如果指定了可选的NO CYCLE关键字,在序列达到最大值后对nextval的任何调用将返回一个错误。如果没有指定CYCLE或NO CYCLE,将保持旧的循环行为。

OWNED BY table_name.column_name
OWNED BY NONE
OWNED BY选项使序列与一个特定的表列相关联,这样,如果该列(或其整个表)被丢弃,序列也将被自动丢弃。如果指定了这个选项,这个关联将取代以前为序列指定的任何关联。指定的表必须有相同的所有者,并且与序列在同一模式下。指定 OWNED BY NONE 会删除任何现有的关联,使序列成为 "独立的"。

new_owner
序列的新所有者的用户名。

new_name
序列的新名称。

new_schema
序列的新schema。

例子

ALTER SEQUENCE pages_id_seq RESTART with 14688;

pages新的序列自增id 将从14688开始

参考