CREATE SEQUENCE — 定义一个新的序列发生器
CREATE [ TEMPORARY | TEMP ] 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
来操作该序列。这些函数在
Section 9.16中有介绍。
尽管无法直接更新一个序列,可以使用这样的查询:
SELECT * FROM name
;
来检查一个序列的参数以及当前状态。特别地,序列的
last_value
域显示被任意会话最后一次取得的值(当然,
在被打印时该值可能已经过时了,因为可能有其他会话正在执行
nextval
调用)。
TEMPORARY
or TEMP
如果被指定,只会为这个会话创建序列对象,并且在会话退出时自动 删除它。当临时序列存在时,已有的同名永久序列(在这个会话中) 会变得不可见,不过可以用模式限定的名称来引用同名永久序列。
IF NOT EXISTS
如果已经存在一个同名的关系时不要抛出错误。这种情况下会发出一个 提示。注意这不保证现有的关系与即将创建的序列相似 -- 它甚至可能 都不是一个序列。
name
要创建的序列的名称(可以是模式限定的)。
data_type
可选的子句AS
指定序列的数据类型。可用的类型是data_type
smallint
、integer
和bigint
。bigint
是默认类型。这个数据类型决定序列的默认最小和最大值。
increment
可选的子句INCREMENT BY
指定为了
创建新值会把哪个值加到当前序列值上。一个正值将会创造一个上升
序列,负值会创造一个下降序列。默认值是 1。
increment
minvalue
NO MINVALUE
可选的子句MINVALUE
决定一个序列
能产生的最小值。如果没有提供这个子句或者指定了
minvalue
NO MINVALUE
,那么会使用默认值。上升序列的默认值是1。下降序列的默认值是其数据类型的最小值。
maxvalue
NO MAXVALUE
可选的子句MAXVALUE
决定该序列
的最大值。如果没有提供这个子句或者指定了
maxvalue
NO MAXVALUE
,那么将会使用默认值。上升序列的默认值是其数据类型的最大值。下降序列的默认值是其数据类型的最大值。
start
可选的子句START WITH
允许序列从任何
地方开始。对于上升序列和下降序列来说,默认的开始值分别是
start
minvalue
和
maxvalue
。
cache
可选的子句CACHE
指定要预分配多少
个序列数并且把它们放在内存中以便快速访问。最小值为 1 (一次只生成
一个值,即没有缓存),默认值也是 1。
cache
CYCLE
NO CYCLE
对于上升序列和下降序列,CYCLE
选项允许序列
在分别达到maxvalue
和minvalue
时回卷。如果达到
该限制,下一个产生的数字将分别是minvalue
和maxvalue
。
如果指定了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
。然后,在该会话中下一次
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扩展。