↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2
历史版本。 PostgreSQL 11 已结束支持。 2023-11-09. 请参阅 当前版本手册.

9.16. 序列操作函数 #

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

表 9.47. 序列函数

函数返回类型描述
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

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

注意

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

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

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

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

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

可用的序列函数如下:

nextval

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

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

这个函数需要序列上的 USAGE 或 UPDATE 权限。

currval

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

这个函数需要序列上的 USAGE 或 SELECT 权限。

lastval

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

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

setval

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

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

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

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

小心

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

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

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

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.