🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# CREATE SEQUENCE ## Name CREATE SEQUENCE -- 定义一个新序列发生器 ## Synopsis ``` CREATE [ TEMPORARY | TEMP ] SEQUENCE _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_` 的单行表。生成器将被使用此命令的用户所有。 如果给出了一个模式名,那么该序列就在给定的模式中创建的。 否则它会在当前模式中创建。临时序列存在于一个特殊的模式中, 因此创建临时序列的时候不能给出模式名。序列名必需和同一模式中的其它序列、 表、索引、视图或外表的名字不同。 在创建序列后,你可以使用`nextval`、 `currval`和`setval`函数操作序列。 这些函数在[Section 9.16](#calibre_link-700)中有详细文档。 尽管你不能直接更新一个序列,但你可以使用: ``` SELECT * FROM _name_; ``` 检查一个序列的参数和当前状态。特别是序列的`last_value` 字段显示了任意会话最后分配的数值。(当然,如果其它会话正积极地使用 `nextval`,这些值在被打印出来的时候可能就已经过时了。) ## 参数 `TEMPORARY` 或 `TEMP` 如果声明了这个修饰词,那么该序列对象只为这个会话创建, 并且在会话结束的时候自动删除。在临时序列存在的时候, 除非用模式修饰的名字引用,否则同名永久序列是不可见的(在同一会话里)。 `_name_` 将要创建的序列名(可以用模式修饰) `_increment_` 可选子句`INCREMENT BY` `_increment_`指定序列的步长。 一个正数将生成一个递增的序列,一个负数将生成一个递减的序列。缺省值是 1 。 `_minvalue_``NO MINVALUE` 可选的子句`MINVALUE` `_minvalue_` 指定序列的最小值。如果没有声明这个子句或者声明了`NO MINVALUE`, 那么递增序列的缺省为 1 ,递减序列的缺省为-2<sup class="calibre28">63</sup>-1。 `_maxvalue_` `NO MAXVALUE` 可选的子句`MAXVALUE` `_maxvalue_` 指定序列的最大值。如果没有声明这个子句或者声明了`NO MAXVALUE`, 那么递增序列的缺省为2<sup class="calibre28">63</sup>-1,递减序列的缺省为 -1 。 `_start_` 可选的子句`START WITH` `_start_` 指定序列的起点。缺省初始值对于递增序列为`_minvalue_`, 对于递减序列为`_maxvalue_`。 `_cache_` 可选的子句`CACHE` `_cache_` 为快速访问而在内存里预先存储多少个序列号。最小值(也是缺省值)是 1 , 表示一次只能生成一个值,也就是说没有缓存。 `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)。 在一些古老的平台上可能没有对八字节整数的编译器支持, 这种情况下序列使用普通的`integer`运算范围(-2147483648 到 +2147483647)。 如果`_cache_`大于一, 并且这个序列对象将被用于多会话并发的场合,那么可能会有不可预料的结果发生。 每个会话在每次访问序列对象的过程中都将分配并缓存随后的序列值, 并且相应增加序列对象的`last_value`。这样, 同一个事务中的随后的`_cache_`-1 次`nextval`将只是返回预先分配的数值,而不是使用序列对象。 因此,任何在会话中分配了却没有使用的数字都将在会话结束时丢失, 从而导致序列里面出现"空洞"。 另外,尽管系统保证为多个会话分配独立的序列值,但是如果考虑所有会话, 那么这个数值可能会丢失顺序。比如,如果`_cache_` 为 10 ,那么会话 A 保留了 1..10 并且返回`nextval`=1, 然后会话 B 可能会保留 11..20 然后在会话 A 生成`nextval`=2 之前返回`nextval`=11。因此,对于 `_cache_`等于一的情况, 可以安全地假设`nextval`值是顺序生成的;而如果把 `_cache_`设置为大于一, 那么你只能假设`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标准, 只有下面的例外: * 还不支持标准的`AS <数据类型>`表达式。 * 使用`nextval()`函数而不是标准的 `NEXT VALUE FOR`表达式获取下一个数值。 * `OWNED BY`子句是PostgreSQL的扩展。 ## 又见 [ALTER SEQUENCE](#calibre_link-621), [DROP SEQUENCE](#calibre_link-619)