CREATE SEQUENCE

CREATE SEQUENCE — 定义一个新的序列生成器

概要

CREATE [ { TEMPORARY | TEMP } | UNLOGGED ] SEQUENCE [ IF NOT EXISTS ] name
    [ AS data_type ]
    [ INCREMENT [ BY ] increment ]
    [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
    [ [ NO ] CYCLE ]
    [ START [ WITH ] start ]
    [ CACHE cache ]
    [ OWNED BY { table_name.column_name | NONE } ]

描述

CREATE SEQUENCE 创建一个新的序列号生成器。这包括创建一个名为 name 的特殊单行表并进行初始化。生成器将由发出命令的用户拥有。

如果给出了模式名,则序列将在指定的模式中创建。否则,它将在当前模式中创建。临时序列存在于一个特殊的模式中,因此在创建临时序列时不能指定模式名。序列名在同一模式中必须与任何其他关系(表、序列、索引、视图、物化视图或外部表)的名称不同。

创建序列后,您可以使用函数 nextval、currval 和 setval 来操作序列。这些函数在 第 9.17 节 中有说明。

虽然您不能直接更新序列,但您可以使用类似以下的查询

SELECT * FROM name;

来检查序列的参数和当前状态。特别是,序列的 last_value 字段显示了由任何会话分配的最后一个值。(当然,如果其他会话正在主动执行 nextval 调用,则此值可能在打印时已过时。)

参数

TEMPORARY 或 TEMP

如果指定,序列对象仅为当前会话创建,并在会话退出时自动删除。与临时序列同名的现有永久序列(在此会话中)不可见,除非使用模式限定名引用它们。

UNLOGGED

如果指定,序列将作为未记录序列创建。未记录序列的更改不会写入预写日志(WAL)。它们不是崩溃安全的:在崩溃或非正常关闭后,未记录序列会自动重置为其初始状态。未记录序列也不会复制到备用服务器。

与未记录表不同,未记录序列并未提供显著的性能优势。此选项主要用于通过标识列或序列列与未记录表相关联的序列。在这些情况下,让序列 WAL 记录和复制,但其关联表不这样做,通常是没有意义的。

IF NOT EXISTS

如果同名关系已存在,则不引发错误。在这种情况下,会发出通知。请注意,不能保证现有关系与可能已创建的序列有任何相似之处 — 它甚至可能不是一个序列。

name

要创建的序列的名称(可选择模式限定)。

data_type

可选子句 AS data_type 指定序列的数据类型。有效类型为 smallint、integer 和 bigint。bigint 是默认值。数据类型决定了序列的默认最小值和最大值。

增量

可选子句 INCREMENT BY increment 指定将哪个值添加到当前序列值以创建新值。正值将创建递增序列,负值将创建递减序列。默认值为 1。

minvalue
NO MINVALUE

可选子句 MINVALUE minvalue 确定序列可以生成的最小值。如果未提供此子句或指定了 NO MINVALUE,则将使用默认值。递增序列的默认值为 1。递减序列的默认值为数据类型的最小值。

maxvalue
NO MAXVALUE

可选子句 MAXVALUE maxvalue 确定序列的最大值。如果未提供此子句或指定了 NO MAXVALUE,则将使用默认值。递增序列的默认值为数据类型的最大值。递减序列的默认值为 -1。

CYCLE
NO CYCLE

CYCLE 选项允许序列在递增序列达到 maxvalue 或递减序列达到 minvalue 时回绕。如果达到限制,下一个生成的数字将分别是 minvalue 或 maxvalue。

如果指定了 NO CYCLE,则在序列达到其最大值后,任何对 nextval 的调用都将返回错误。如果未指定 CYCLE 或 NO CYCLE,则 NO CYCLE 是默认值。

start

可选子句 START WITH start 允许序列从任意位置开始。递增序列的默认起始值为 minvalue,递减序列的默认起始值为 maxvalue。

cache

可选子句 CACHE cache 指定有多少序列号将被预分配并存储在内存中以便更快访问。最小值是 1(一次只能生成一个值,即没有缓存),这也是默认值。

OWNED BY table_name.column_name
OWNED BY NONE

OWNED BY 选项使序列与特定的表列关联,这样,如果该列(或其整个表)被删除,序列也将被自动删除。指定的表必须与序列拥有者相同,并且在同一模式下。 OWNED BY NONE 是默认值,表示没有这种关联。

注释

使用 DROP SEQUENCE 删除序列。

序列基于 bigint 算术,因此范围不能超过 8 字节整数的范围(-9223372036854775808 到 9223372036854775807)。

由于 nextval 和 setval 调用从不回滚,因此如果需要“无间隙”分配序列号,则不能使用序列对象。可以通过独占锁定一个包含计数器的表来构建无间隙分配;但这比序列对象昂贵得多,尤其是在许多事务需要并发访问序列号的情况下。

如果用于将要由多个会话并发使用的序列对象的 cache 设置大于一,可能会获得意外结果。每个会话将在一次访问序列对象时分配和缓存连续的序列值,并相应地增加序列对象的 last_value。然后,该会话中 nextval 的下 cache-1 次使用将仅返回预分配的值,而无需触及序列对象。因此,任何在会话中分配但未使用过的数字将在该会话结束时丢失,从而在序列中产生“间隙”。

此外,虽然保证多个会话会分配不同的序列值,但在考虑所有会话时,这些值可能会乱序生成。例如,如果 cache 设置为 10,会话 A 可能会保留值 1..10 并返回 nextval=1,然后会话 B 可能会保留值 11..20 并返回 nextval=11,而此时会话 A 尚未生成 nextval=2。因此,当 cache 设置为 1 时,可以安全地假设 nextval 值是按顺序生成的;当 cache 设置大于 1 时,您只能假设 nextval 值是不同的,而不是它们是严格按顺序生成的。另外,last_value 将反映任何会话保留的最新值,无论该值是否已由 nextval 返回。

另一个需要考虑的是,在这样的序列上执行的 setval 不会被其他会话注意到,直到它们用完任何已缓存的预分配值。

示例

创建一个名为 serial 的递增序列,从 101 开始

CREATE SEQUENCE serial START 101;

从此序列中选择下一个数字

SELECT nextval('serial');

 nextval
---------
     101

从此序列中选择下一个数字

SELECT nextval('serial');

 nextval
---------
     102

在 INSERT 命令中使用此序列

INSERT INTO distributors VALUES (nextval('serial'), 'nothing');

在 COPY FROM 后更新序列值

BEGIN;
COPY distributors FROM 'input_file';
SELECT setval('serial', max(id)) FROM distributors;
END;

兼容性

CREATE SEQUENCE 符合SQL标准,但有以下例外:

  • 获取下一个值是通过 nextval() 函数完成的,而不是使用标准的 NEXT VALUE FOR 表达式。

  • OWNED BY 子句是 PostgreSQL 的扩展。