==================  序列操作函数 ================== .. container:: sect1 :name: FUNCTIONS-SEQUENCE .. container:: titlepage .. container:: .. container:: .. rubric:: 序列操作函数 :name: 序列操作函数 :class: title 本节描述用于操作\ *序列对象*\ 的函数,序列对象也被称为序列生成器或者就是序列。序列对象都是用\ `CREATE SEQUENCE `__\ 创建的特殊的单行表。序列对象通常用于为表的行生成唯一的标识符。\ `表 序列函数 `__\ 中列出的这些序列函数,可以为我们从序列对象中获取连续的序列值提供了简单的、多用户安全的 方法。 .. container:: table :name: FUNCTIONS-SEQUENCE-TABLE **序列函数** .. container:: table-contents +---------------------------+------------+---------------------------+ | 函数 | 返回类型 | 描述 | +===========================+============+===========================+ | ``currval(regclass``) | ``bigint`` | 返回最近一次用\ ``next | | | | val``\ 获取的指定序列的值 | +---------------------------+------------+---------------------------+ | ``lastval()`` | ``bigint`` | 返回最近一次用\ ``next | | | | val``\ 获取的任何序列的值 | +---------------------------+------------+---------------------------+ | ``nextval(regclass``) | ``bigint`` | 递增序列并返回新值 | +---------------------------+------------+---------------------------+ | ``setval(regclass``, | ``bigint`` | 设置序列的当前值 | | ``bigint``) | | | +---------------------------+------------+---------------------------+ | ``setval(regclass``, | ``bigint`` | 设置序列的当前值 | | ``bigint``, ``boolean``) | | 以及\ ``is_called``\ 标志 | +---------------------------+------------+---------------------------+ 将要由序列函数调用操作的序列是用一个\ ``regclass``\ 参数声明的, 它只是序列在\ ``pg_class``\ 系统表里面的 OID。不过,你不需要手工查找 OID, 因为\ ``regclass``\ 数据类型的输入转换器会帮你做这件事情。 只要写出用单引号包围的序列名字即可,因此它看上去像文本常量。为了和普通SQL名字处理兼容,这个字串将转换成小写形式, 除非在序列名字周围包含双引号。因此: .. code:: programlisting nextval('foo') 操作序列foo nextval('FOO') 操作序列foo nextval('"Foo"') 操作序列Foo 必要时序列名可以用模式限定∶ .. code:: programlisting nextval('myschema.foo') 操作myschema.foo nextval('"myschema".foo') 同上 nextval('foo') 在搜索路径中查找foo 参阅\ `Oid数据类型 `__\ 获取有关\ ``regclass``\ 的更多信息。 .. note:: .. rubric:: 注意 :name: 注意 :class: title 当你把一个序列函数的参数写成一个无修饰的文字串,那么它将变成类型为\ ``regclass``\ 的常量。因为这只是一个 OID,它将跟踪最初标识的序列,而不管后面是否改名、模式变化等等。 这种“早期绑定”的行为通常是列默认值和视图中引用的序列所需要的。 但是有时候你可能想要“延迟绑定”,其中序列的引用是在运行时解析的。要得到延迟绑定的行为,我们可以强制常量被存储为\ ``text``\ 常量,而不是\ ``regclass``\ : .. code:: programlisting nextval('foo'::text) foo在运行时查找 当然,序列函数的参数也可以是表达式。如果它是一个文本表达式,那么隐式的转换将导致运行时的查找。 可用的序列函数有∶ .. container:: variablelist ``nextval`` 递增序列对象到它的下一个值并且返回该值。这个动作是自动完成的: 即使多个会话并发执行\ ``nextval``\ ,每个进程也会安全地收到一个唯一的序列值。 如果一个序列对象是用默认参数创建的,连续的\ ``nextval``\ 调用将会返回从 1 开始的连续的值。其他的行为可以通过在\ `CREATE SEQUENCE `__\ 命令中使用特殊参数来获得;详见该命令的参考页。 .. important:: .. rubric:: 重要 :name: 重要 :class: title 为了避免阻塞从同一个序列获取序号的并发事务,\ ``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``\ 报告的值不会被改变。 例如: .. code:: screen SELECT setval('foo', 42); 下一次nextval会返回 43 SELECT setval('foo', 42, true); 同上 SELECT setval('foo', 42, false); 下一次nextval将返回 42 ``setval``\ 返回的结果就是它的第二个参数的值。 .. important:: .. rubric:: 重要 :name: 重要-1 :class: title 因为序列是非事务的,\ ``setval``\ 造成的改变不会由于事务的回滚而撤销。 这个函数要求序列上的\ ``UPDATE``\ 特权。