ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 9.16\. 序列操作函数 本节描述用于操作_序列对象_的函数, 也叫序列生成器或者就叫序列。序列对象都是用[CREATE SEQUENCE](#calibre_link-42) 创建的特殊的单行表。一个序列对象通常用于为一个表的行生成唯一的标识符。 在[Table 9-41](#calibre_link-2231) 中列出的序列函数为我们从序列对象中获取后续的序列值提供了简单的、多用户安全的方法。 **Table 9-41\. 序列函数** | 函数 | 返回类型 | 描述 | | --- | --- | --- | | ``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.18](#calibre_link-1152)获取有关`regclass`的更多信息。 > **Note:** 在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](#calibre_link-42) 命令里的特殊参数获取;参考其命令参考页获取更多信息。 > **Important:** 为了避免从同一个序列获取数值的当前事务被阻塞,`nextval` 操作决不会回滚;也就是说,一旦一个数值已经被抓走,那么就认为它已经用过了, 即使调用`nextval`的事务后面又退出了也一样。 这就意味着退出的事务可能在序列赋予的数值中留下未使用的"空洞"。 `currval` 在当前会话中返回最近一次`nextval`抓到的该序列的数值。 如果在本会话中从未在该序列上调用过`nextval`,那么会报告一个错误。 因为此函数返回一个会话范围的数值,它也能给出一个可预计的结果, 可以判断其它会话是否执行过`nextval`函数。 `lastval` 返回当前会话里最近一次`nextval`返回的数值。这个函数等效于`currval`, 只是它不用序列名作为参数,它抓取当前会话里面最近一次`nextval` 使用的序列的值。如果当前会话还没有调用过`nextval`, 那么调用`lastval`是会报错的。 `setval` 重置序列对象的计数器数值。2个参数的形式设置序列的`last_value` 字段为声明数值并且将其`is_called`字段设置为`true`, 表示下一次`nextval`将在返回数值之前递增该序列。`currval` 报告的值也设定为指定的值。在3个参数形式里`is_called`可以设置为`true` 或`false`。设置为`true`和2参数的形式影响相同。 如果你把它设置为`false`,那么下一次`nextval` 将返回这里声明的数值而随后`nextval`才开始递增该序列。 因此在这种情况下`currval`报告的值没有改变(这是8.3之前版本的一个变化)。比如, ``` SELECT setval('foo', 42); _下次`nextval`将返回43_ SELECT setval('foo', 42, true); _和上面一样_ SELECT setval('foo', 42, false); _下次`nextval`将返回42_ ``` `setval`返回的结果就是它的第二个参数的数值。 > **Important:** 因为序列是非事务性的,如果事务回滚了,由`setval`所做的改变也不会取消。