创建序列
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 ]
[ START [ WITH ] start ] [ CACHE cache ] [ [ 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如果指定,则序列将创建为未记录序列。对未记录序列的更改不会写入预写日志。它们不是防崩溃的:未记录序列在崩溃或不干净关机后会自动重置为其初始状态。未记录序列也不会复制到备用服务器。
与未记录表不同,未记录序列不会提供显著的性能优势。此选项主要用于通过标识列或序列列与未记录表关联的序列。在这些情况下,通常没有必要对序列进行 WAL 记录和复制,但对其关联表不进行这些操作。
IF NOT EXISTS如果已存在具有相同名称的关系,则不引发错误。在这种情况下,将发出通知。请注意,无法保证现有关系与将创建的序列类似 — 它甚至可能不是序列。
name要创建的序列的名称(可选地限定架构)。
数据类型可选子句
AS指定序列的数据类型。有效类型为data_typesmallint、integer和bigint。默认值为bigint。数据类型决定序列的默认最小值和最大值。增量可选子句
INCREMENT BY指定添加到当前序列值以创建新值的值。正值将生成升序序列,负值将生成降序序列。默认值为 1。incrementminvalueNO MINVALUE可选子句
MINVALUE确定序列可以生成的最小值。如果未提供此子句或指定minvalueNO MINVALUE,则将使用默认值。升序序列的默认值为 1。降序序列的默认值为数据类型的最小值。maxvalueNO MAXVALUE可选子句
MAXVALUE确定序列的最大值。如果未提供此子句或指定maxvalueNO MAXVALUE,则将使用默认值。升序序列的默认值为数据类型的最大值。降序序列的默认值为 -1。开始可选子句
START WITH允许序列从任意位置开始。升序序列的默认起始值为startminvalue,降序序列的默认起始值为maxvalue。缓存可选子句
CACHE指定为加快访问速度而预先分配并存储在内存中的序列号数量。最小值为 1(一次只能生成一个值,即无缓存),这也是默认值。cacheCYCLENO CYCLECYCLE选项允许序列在升序或降序序列分别达到maxvalue或minvalue时循环。如果达到限制,则生成的下一个数字将分别为minvalue或maxvalue。如果指定
NO CYCLE,则在序列达到其最大值后对nextval的任何调用都将返回错误。如果未指定CYCLE或NO CYCLE,则默认值为NO CYCLE。OWNED BYtable_name.column_nameOWNED BY NONEOWNED 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 并返回`nextval`=11,而会话 A 尚未生成`nextval`=2。因此,如果*`cache`*设置设为 1,则可以安全地假设`nextval`值是按顺序生成的;如果*`cache`*设置大于 1,则你只能假设`nextval`值是不同的,而不是按顺序生成的。此外,`last_value`将反映任何会话保留的最新值,无论`nextval`是否已返回该值。
另一个需要考虑的问题是,针对此类序列执行的`setval`不会被其他会话注意到,直到它们用尽已缓存的任何预分配值。
## 示例
创建一个从 101 开始的升序序列,名为`serial`
```
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标准,但有以下例外
<ul class="itemizedlist" style="list-style-type: disc;">
<li class="listitem">
<p>使用<code class="function">nextval()</code>函数获取下一个值,而不是标准的<code class="command">NEXT VALUE FOR</code>表达式。</p>
</li>
<li class="listitem">
<p><code class="literal">OWNED BY</code>子句是<span class="productname">PostgreSQL</span>扩展。</p>
</li>
</ul>
## 另请参见
[ALTER SEQUENCE](sql-altersequence.html)、[DROP SEQUENCE](sql-dropsequence.html)`