PostgreSQL 13.1 中文入门教程 PostgreSQL 序列操作函数

2024-02-25 开发教程 PostgreSQL 13.1 中文入门教程 匿名 4

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

表 9.50. 序列函数

函数

描述

nextval( regclass) → bigint

将序列对象推进到下一个值并返回该值。这是自动完成的:即使多个会话并发地执行nextval,每个会话也会安全地接收到不同的序列值。 如果序列对象是用默认形参创建的,则连续的nextval调用将返回以1开始的连续值。 其他行为可以通过在 CREATE SEQUENCE 命令中使用适当的参数获得。

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

setval( regclass, bigint[, boolean] ) → bigint

设置序列对象的当前值,以及可选的它的is_called标志。 双参数形式将序列的last_value字段设置为指定的值,并将其is_called字段设置为true,意味着下一个nextval将在返回值之前推进序列。 currval将报告的值也设置为指定的值。在三参数形式中,is_called可以设置为truefalsetrue与双参数形式具有相同的效果。 如果设置为false,下一个nextval将返回指定的值,序列推进从下面的 nextval开始。 而且,currval报告的值在这种情况下不会改变。例如,

SELECT setval('myseq', 42);           Next nextval will return 43
SELECT setval('myseq', 42, true); Same as above
SELECT setval('myseq', 42, false); Next nextval will return 42

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

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

currval( regclass) → bigint

返回nextval在当前会话中为该序列最近获取的值。(如果在这个会话中没有为这个序列调用nextval会报告错误。) 因为它返回的是一个会话本地值,所以它给出了一个可预测的答案,即自当前会话以来,其他会话是否执行了nextval

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

lastval() → bigint

返回nextval在当前会话中最近返回的值。这个函数与currval相同,不同之处在于它没有使用序列名作为参数,而是引用当前会话中nextval最近应用到的序列。 如果在当前会话中还没有调用nextval,那么调用lastval是一个错误。

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

小心

为了避免阻塞从相同序列中获取数字的并发事务,nextval操作永远不会回滚;也就是说,一旦获取了一个值,它就会被认为是已使用的,并且不会再次返回。 即使周围的事务随后中止,或者调用查询最终没有使用该值,也会出现这种情况。 例如,带有ON CONFLICT子句的INSERT将计算要插入的元组,包括执行任何必需的nextval调用,在检测到任何可能导致它遵循 ON CONFLICT规则的冲突之前。 这种情况会在赋值序列中留下未使用的“holes”。因此,PostgreSQL序列对象不能被用于获取 “gapless”序列 。

同样的,如果事务回滚,setval所做的任何序列状态更改都不会撤消。

序列函数所要操作的序列由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

关于regclass的更多信息请参见第 8.19 节。

注意

在PostgreSQL 8.1 之前,序列函数的参数类型是text, 而不是 regclass,并且前文所述的从文本串到 OID 值的转换将在每次调用的时候发生。 为了向后兼容,这个处理仍然存在,但是在内部实际上是通过在函数调用前隐式地将text转换成regclass实现的。

当你把一个序列函数的参数写成一个无修饰的文字串,那么它将变成类型为regclass的常量。 因为这只是一个 OID,它将跟踪最初标识的序列,而不管后面是否改名、模式变化等等。 这种“早期绑定”的行为通常是列默认值和视图中引用的序列所需要的。 但是有时候你可能想要“延迟绑定”,其中序列的引用是在运行时解析的。 要得到延迟绑定的行为,我们可以强制常量被存储为text常量,而不是regclass

nextval('foo'::text)      foo is looked up at runtime

请注意,延迟绑定是PostgreSQL版本 8.1 之前唯一被支持的行为, 因此你可能需要做这些来保留旧应用的语义。

当然,序列函数的参数也可以是表达式。如果它是一个文本表达式,那么隐式的转换将导致运行时的查找。