选择 打开 改范围 完整检索页
受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10
当前 PostgreSQL 版本不在支持生命周期内。
您可以参阅当前版本的对应页面,或其他在上面列出的活跃大版本。

9.16. 序列操作函数 #

本节描述对序列对象进行操作的函数,也称为序列生成器或简称序列。 序列对象是使用CREATE SEQUENCE创建的特殊单行表。 序列对象通常用于为表中的行生成惟一标识符。在Table 9.50中列出的序列函数,提供了简单的、多用户安全方法,用于从序列对象中获取连续的序列值。

Table 9.50. 序列函数

函数 返回类型 描述
currval(regclass) bigint 返回最近对指定序列调用 nextval 得到的值
lastval() bigint 返回最近对任意序列调用 nextval 得到的值
nextval(regclass) bigint 推进序列并返回新值
setval(regclass, bigint) bigint 设置序列的当前值
setval(regclass, bigint, boolean) bigint 设置序列的当前值和 is_called 标志

序列函数要操作的序列由一个regclass参数指定,该参数就是序列在pg_class系统目录中的 OID。不过,不必手动查找 OID,因为regclass数据类型的输入转换函数会替你完成这项工作。只需将序列名用单引号括起来,使其看上去像一个字面常量。为兼容普通SQL名称的处理方式,除非序列名被双引号括起,否则字符串会转换为小写。因此:

nextval('foo')      操作序列 foo
nextval('FOO')      操作序列 foo
nextval('"Foo"')    操作序列 Foo

必要时,序列名可以带模式限定:

nextval('myschema.foo')     操作 myschema.foo
nextval('"myschema".foo')   同上
nextval('foo')              在搜索路径中查找 foo

参见Section 8.19以获取更多有关以下类型的信息:regclass

Note

PostgreSQL 8.1 之前,序列函数的参数类型是 text,而不是 regclass;上述从文本字符串到 OID 值的转换会在每次调用时于运行期间执行。为保持向后兼容,这种能力仍然存在,但内部现在会在调用函数前,通过从 textregclass 的隐式强制转换来处理。

将序列函数的参数写成不加修饰的字符串字面量时,它会成为以下类型的常量:regclass。由于它实际上只是一个 OID,即使后来发生重命名、模式变更等情况,它仍会指向最初标识的序列。这种早绑定行为通常适用于列默认值和视图中的序列引用。但有时你可能希望采用后绑定,在运行时解析序列引用。要获得后期绑定行为,应强制将常量存储为text常量,而不是regclass

nextval('foo'::text)      foo运行时被查找

请注意,后期绑定是下列旧版本唯一支持的行为:PostgreSQL8.1 之前的版本,因此可能需要这样做来保留旧应用的语义。

当然,序列函数的参数既可以是常量,也可以是表达式。如果它是文本表达式,隐式强制转换就会导致运行时查找。

可用的序列函数如下:

nextval

将序列对象推进到下一个值并返回该值。这个操作是原子的:即使多个会话并发执行 nextval,每个会话也会安全地获得一个不同的序列值。

如果使用默认参数创建序列对象,连续调用 nextval 会返回从 1 开始的连续值。可以在 CREATE SEQUENCE 命令中使用特殊参数获得其他行为;更多信息请参见该命令的参考页。

这个函数需要USAGEUPDATE权限在序列上。

currval

返回当前会话中最近一次针对该序列调用 nextval 所获得的值。(如果当前会话从未针对该序列调用过 nextval,则会报错。)由于返回的是会话局部值,无论其他会话是否在当前会话调用之后执行过 nextval,结果都是可预测的。

这个函数需要序列上的USAGESELECT权限。

lastval

返回当前会话中最近一次调用 nextval 所返回的值。此函数与 currval 相同,但不接受序列名参数,而是引用当前会话中最近一次调用 nextval 时所操作的序列。如果当前会话尚未调用过 nextval,调用 lastval 会报错。

该函数在最后使用的序列上需要USAGESELECT权限。

setval

重置序列对象的计数器值。双参数形式将序列的last_value字段设为指定值,并将其is_called字段设为true,这意味着下次调用nextval会在返回值之前推进序列。currval报告的值也会设为指定值。在三参数形式中,is_called可以设为truefalsetrue与双参数形式具有相同的效果。如果将它设为false,下次调用nextval将恰好返回指定值,并从再下一次调用nextval时开始推进序列。此外,在这种情况下,currval报告的值不会改变。例如:

SELECT setval('foo', 42);           下一次 nextval 将返回 43
SELECT setval('foo', 42, true);     同上
SELECT setval('foo', 42, false);    下一次 nextval 将返回 42

函数setval返回的结果就是其第二个参数的值。

这个函数在序列上需要UPDATE权限。

Caution

为了避免阻塞从相同序列获取数字的并发事务,nextval获得的值如果调用事务后续中止,就不会被重新使用。 这意味着事务中止或数据库崩溃可能导致分配值序列中的间隙。这也可能发生在没有事务中止的情况下。 例如,带有ON CONFLICT子句的INSERT将计算要插入的元组,包括执行任何必需的nextval调用, 然后才检测到可能导致其遵循ON CONFLICT规则的任何冲突。 因此,PostgreSQL序列对象不能用于获取无间隙序列

同样,setval函数所做的序列状态更改立即对其他事务可见, 并且如果调用事务回滚,则不会被撤消。

如果在包含nextvalsetval调用的事务提交之前, 数据库集簇崩溃,那么序列状态更改可能尚未传递到持久存储, 因此在集簇重新启动后,无法确定序列是保持其原始状态还是更新状态。 对于数据库内部使用序列而言,这是无害的,因为未提交事务的其他影响也不会可见。 但是,如果您希望将序列值用于持久性的数据库外部用途,请确保在这样做之前已经提交了nextval调用。