阅读(1747) (13)

PostgreSQL CREATE SEQUENCE

2021-08-23 14:27:08 更新

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

大纲

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

描述

CREATE SEQUENCE创建一个新的序列数 发生器。这涉及到用名称name创建并且初始化 一个新的特殊的单行表。该发生器将由发出该命令的用户所拥有。

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

在序列被创建后,可以使用函数 nextvalcurrval以及 setval来操作该序列。这些函数在 第 9.17 节中有介绍。

尽管无法直接更新一个序列,可以使用这样的查询:

SELECT * FROM name;

来检查一个序列的参数以及当前状态。特别地,序列的 last_value域显示被任意会话最后一次取得的值(当然, 在被打印时该值可能已经过时了,因为可能有其他会话正在执行 nextval调用)。

参数

TEMPORARY or TEMP

如果被指定,只会为这个会话创建序列对象,并且在会话退出时自动 删除它。当临时序列存在时,已有的同名永久序列(在这个会话中) 会变得不可见,不过可以用模式限定的名称来引用同名永久序列。

IF NOT EXISTS

如果已经存在一个同名的关系时不要抛出错误。这种情况下会发出一个 提示。注意这不保证现有的关系与即将创建的序列相似 — 它甚至可能 都不是一个序列。

name

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

data_type

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

increment

可选的子句INCREMENT BY increment 指定为了 创建新值会把哪个值加到当前序列值上。一个正值将会创造一个上升 序列,负值会创造一个下降序列。默认值是 1。

minvalue
NO MINVALUE

可选的子句MINVALUE minvalue 决定一个序列 能产生的最小值。如果没有提供这个子句或者指定了 NO MINVALUE,那么会使用默认值。 升序序列的默认值为1。降序序列的默认值为数据类型的最小值。

maxvalue
NO MAXVALUE

可选的子句MAXVALUE maxvalue 决定该序列 的最大值。如果没有提供这个子句或者指定了 NO MAXVALUE,那么将会使用默认值。 升序序列的默认值是数据类型的最大值。降序序列的默认值是-1。

start

可选的子句START WITH start 允许序列从任何 地方开始。对于上升序列和下降序列来说,默认的开始值分别是 minvaluemaxvalue

cache

可选的子句CACHE cache 指定要预分配多少 个序列数并且把它们放在内存中以便快速访问。最小值为 1 (一次只生成 一个值,即没有缓存),默认值也是 1。

CYCLE
NO CYCLE

对于上升序列和下降序列,CYCLE选项允许序列 在分别达到maxvalueminvalue时回卷。如果达到 该限制,下一个产生的数字将分别是minvaluemaxvalue

如果指定了NO CYCLE,当序列到达其最大值 后任何nextval调用将返回一个错误。如果 CYCLENO CYCLE都没有 被指定,则默认为NO CYCLE

OWNED BY table_name.column_name
OWNED BY NONE

OWNED BY选项导致序列被与一个特定的表列关联 在一起,这样如果该列(或者整个表)被删除,该序列也将被自动删除。 指定的表必须和序列具有相同的拥有者并且在同一个模式中。默认选项 OWNED BY NONE指定该序列不与某个列关联。

注解

使用DROP SEQUENCE移除一个序列。

序列是基于bigint算法的,因此范围是不能超过一个八字节 整数的范围(-9223372036854775808 到 9223372036854775807)。

由于nextvalsetval调用绝不会回滚, 如果需要序数的无间隙分配,则不能使用序列对象。可以 通过在一个只包含一个计数器的表上使用排他锁来构建无间隙的分配, 但是这种方案比序列对象开销更大,特别是当有很多事务并发请求序数 时。

如果对一个将由多个会话并发使用的序列对象使用了大于 1 的cache设置,可能会得到意想不到的结果。 每个会话会在访问该序列对象时分配并且缓存后续的序列值,并且相应地增加 该序列对象的last_value。然后,在该会话中下一次 nextval会做 cache-1,并且简单地 返回预分配的值而不修改序列对象。因此,任何已分配但没有在会话中使用的 数字将会在该会话结束时丢失,导致该序列中的空洞

进一步,尽管多个会话能分配到不同的序列值,这些值可能会在所有会话都被 考虑时生成出来。例如, cache的设置为 10,会话 A 可能储存值 1..10 并且返回nextval=1,然后会话 B 可能储存值 11..20 并且在 A 生成nextval=2 之前返回 nextval=11。因此,如果 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扩展。