CREATE SEQUENCE — 定义新的序列生成器
CREATE [ { TEMPORARY | TEMP } | UNLOGGED ] SEQUENCE [ IF NOT EXISTS ]name
[ ASdata_type
] [ INCREMENT [ BY ]increment
] [ MINVALUEminvalue
| NO MINVALUE ] [ MAXVALUEmaxvalue
| NO MAXVALUE ] [ START [ WITH ]start
] [ CACHEcache
] [ [ NO ] CYCLE ] [ OWNED BY {table_name
.column_name
| NONE } ]
CREATE SEQUENCE
创建新的序列号生成器。这涉及创建和初始化一个新的带有名称 name
的特殊单行表。生成器归发出该命令的用户所有。
如果给出了架构名称,则序列在指定的架构中创建。否则,它在当前架构中创建。临时序列存在于特殊架构中,因此创建临时序列时不能给出架构名称。序列名称必须不同于同一架构中的任何其他关系名称(表、序列、索引、视图、物化视图或外部表)。
创建序列后,使用函数 nextval
、currval
和 setval
对序列进行操作。这些函数在 第 9.17 节 中记录。
虽然您无法直接更新序列,但可以使用类似如下的查询
SELECT * FROM name
;
检查序列的参数和当前状态。特别是,序列的 last_value
字段显示了最后一次由任何会话分配的值。(当然,如果其他会话正在积极调用 nextval
),那么在打印该值时,该值可能已过时。
TEMPORARY
或 TEMP
如果指定,则仅针对此会话创建序列对象,并且在会话退出时自动删除。在临时序列存在期间(除非使用按架构限定的名称引用),具有相同名称的现有持久序列(在此会话中)不可见。
UNLOGGED
如果指定,则序列被创建为未记录的序列。未记录的序列的更改不会写入预写式日志。它们不支持故障保护:未记录的序列在崩溃或 unclean shutdown 后会自动重置为其初始状态。未记录的序列也不会复制到备用服务器。
与未记录的表不同,未记录的序列不会提供显著的性能优势。此选项主要用于通过标识列或序列列与未记录的表关联的序列。在这些情况下,如果记录序列 WAL 并且复制序列,而未记录与其关联的表,通常是没有意义的。
IF NOT EXISTS
如果已存在具有相同名称的关系,则不抛出错误。在这种情况下,会发出通知。请注意,无法保证现有关系与即将创建的序列类似 - 甚至可能不是序列。
name
要创建的序列的名称(可以选择架构限定)。
data_type
可选子句 AS
指定序列数据类型。有效类型为 数据类型
smallint
、integer
和 bigint
。默认值是 bigint
。数据类型决定了序列的默认最小值和最大值。
增量
可选子句 INCREMENT BY
指定要添加到当前序列值中以生成一个新值的数字。正数将产生一个递增序列,而负数则产生一个递减序列。该默认值为 1。增量
最小值
无最小值
可选子句 MINVALUE
决定序列可以生成的最小值。如果未提供此子句或指定了 最小值
无最小值
,则使用默认值。对于递增序列,默认值为 1。对于递减序列,默认值为该数据类型的最小值。
最大值
无最大值
可选子句 MAXVALUE
决定序列的最大值。如果未提供此子句或指定了 最大值
无最大值
,则使用默认值。对于递增序列,默认值为该数据类型的最大值。对于递减序列,默认值为 -1。
起点
可选子句 START WITH
允许序列从任何地方开始。对于递增序列,默认起始值为 起点
最小值
,而对于递减序列,默认起始值为 最大值
。
缓存
可选子句 CACHE
指定要预先分配并存储在内存中以加速访问的序列数。最小值为 1(一次只能生成一个值,即无缓存),这也是默认值。缓存
CYCLE
NO CYCLE
CYCLE
选项允许在一个递增或递减序列达到 最大值
或 最小值
时序列进行环回。如果达到上限,则下一个生成的数字将分别是 最小值
或 最大值
。
如果指定 NO CYCLE
,则在序列达到其最大值后,对 nextval
的任何调用都将返回一个错误。如果没有指定 CYCLE
或 NO CYCLE
,则 NO CYCLE
为默认值。
OWNED BY
table_name
.column_name
OWNED BY NONE
OWNED BY
选项会使该序列与特定表列相关联,因此,如果该列(或其整个表)被删除,该序列也会被自动删除。指定表必须具有与序列相同的拥有者,且必须与序列位于同一架构中。 OWNED BY NONE
(默认选项)指定不存在此类关联。
使用 DROP SEQUENCE
删除序列。
序列基于 bigint
算术,因此范围不能超过八字节整数的范围(-9223372036854775808 至 9223372036854775807)。
由于 nextval
和 setval
调用永不回滚,因此如果需要序列号的“无缝隙”分配,就无法使用序列对象。可以通过对包含计数器的表采用独占锁定,构建无缝隙分配;但与序列对象相比,这种解决方案的成本更高,尤其在许多事务同时需要序列号的情况下。
如果对多个会话将并发使用的序列对象使用大于 1 的 cache
设置,则可能会导致意外结果。每次访问序列对象时,每个会话都会分配并缓存后续序列值,并相应增加序列对象的 last_value
。然后,该会话中 cache
-1 的下一次 nextval
使用仅仅返回预分配值,而不接触序列对象。因此,任何在会话中被分配但未使用的编号在会话结束时都会丢失,从而导致序列中的“空洞”。
此外,虽然多个会话保证分配不同的序列值,但当考虑所有会话时,这些值可能生成为非顺序形式。例如,当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
在其他会话使用完任何预先分配的已缓存值之前,其他会话不会注意到 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 扩展。