Skip to content

创建序列

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*。该生成器将归属发出该命令的用户所有。

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

创建序列后,使用函数nextvalcurrvalsetval对序列进行操作。这些函数在第 9.17 节中进行了说明。

虽然无法直接更新序列,但可以使用类似于以下内容的查询

SELECT * FROM name;

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

参数

TEMPORARYTEMP

如果指定,则仅为该会话创建序列对象,并在会话退出时自动删除。只要使用架构限定名称引用,则在临时序列存在时,具有相同名称的现有永久序列将不可见(在此会话中)。

UNLOGGED

如果指定,则序列将创建为未记录序列。对未记录序列的更改不会写入预写日志。它们不是防崩溃的:未记录序列在崩溃或不干净关机后会自动重置为其初始状态。未记录序列也不会复制到备用服务器。

与未记录表不同,未记录序列不会提供显著的性能优势。此选项主要用于通过标识列或序列列与未记录表关联的序列。在这些情况下,通常没有必要对序列进行 WAL 记录和复制,但对其关联表不进行这些操作。

IF NOT EXISTS

如果已存在具有相同名称的关系,则不引发错误。在这种情况下,将发出通知。请注意,无法保证现有关系与将创建的序列类似 — 它甚至可能不是序列。

name

要创建的序列的名称(可选地限定架构)。

数据类型

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

增量

可选子句 INCREMENT BY increment 指定添加到当前序列值以创建新值的值。正值将生成升序序列,负值将生成降序序列。默认值为 1。

minvalue
NO MINVALUE

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

maxvalue
NO MAXVALUE

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

开始

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

缓存

可选子句 CACHE cache 指定为加快访问速度而预先分配并存储在内存中的序列号数量。最小值为 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)。

因为`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)`