本节描述用于操作序列对象的函数,序列对象也被称为序列生成器或者就是序列。序列对象都是用CREATE SEQUENCE创建的特殊的单行表。序列对象通常用于为表的行生成唯一的标识符。表 9.47中列出的这些序列函数,可以为我们从序列对象中获取连续的序列值提供了简单的、多用户安全的 方法。
表 9.47. 序列函数
函数 | 返回类型 | 描述 |
---|---|---|
| bigint | 返回最近一次用nextval 获取的指定序列的值 |
| bigint | 返回最近一次用nextval 获取的任何序列的值 |
| bigint | 递增序列并返回新值 |
| bigint | 设置序列的当前值 |
| 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.18 节获取有关regclass
的更多信息。
在PostgreSQL 8.1 之前,序列函数的参数类型是text
, 而不是 regclass
,并且前文所述的从文本串到 OID 值的转换将在每次调用的时候发生。 为了向后兼容,这个处理仍然存在,但是在内部实际上是通过在函数调用前隐式地将text
转换成regclass
实现的。
当你把一个序列函数的参数写成一个无修饰的文字串,那么它将变成类型为regclass
的常量。因为这只是一个 OID,它将跟踪最初标识的序列,而不管后面是否改名、模式变化等等。 这种“早期绑定”的行为通常是列默认值和视图中引用的序列所需要的。 但是有时候你可能想要“延迟绑定”,其中序列的引用是在运行时解析的。要得到延迟绑定的行为,我们可以强制常量被存储为text
常量,而不是regclass
:
nextval('foo'::text) foo
在运行时查找
请注意,延迟绑定是PostgreSQL版本 8.1 之前唯一被支持的行为, 因此你可能需要做这些来保留旧应用的语义。
当然,序列函数的参数也可以是表达式。如果它是一个文本表达式,那么隐式的转换将导致运行时的查找。
可用的序列函数有∶
nextval
递增序列对象到它的下一个值并且返回该值。这个动作是自动完成的: 即使多个会话并发执行nextval
,每个进程也会安全地收到一个唯一的序列值。
如果一个序列对象是用默认参数创建的,连续的nextval
调用将会返回从 1 开始的连续的值。其他的行为可以通过在CREATE SEQUENCE命令中使用特殊参数来获得;详见该命令的参考页。
为了避免从同一个序列获取值的并发事务被阻塞,
nextval
操作决不会回滚;也就是说,一旦一个值已经被抓取,
那么就认为它已经被用过了,并且不会再被返回。
即使周围的事务之后中断,或者如果调用查询结束不使用该值,那么为真。
例如,带有ON CONFLICT
的INSERT
子句将计算被插入的元组,
包括执行任何所需的nextval
调用,
相反检测任何冲突之前将导致它遵循ON CONFLICT
规则。
这种情况将在指定值的顺序中留下未使用的“空洞”。
因此,PostgreSQL序列对象不能用于获得“无间隙”序列。
该函数需要序列上的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
返回的结果就是它的第二个参数的值。
因为序列是非事务的,setval
造成的改变不会由于事务的回滚而撤销。
该函数需要序列上的UPDATE
权限。