=============== CREATE SEQUENCE =============== .. container:: refentry :name: SQL-CREATESEQUENCE .. container:: titlepage .. container:: refnamediv .. rubric:: CREATE SEQUENCE :name: create-sequence CREATE SEQUENCE — 定义一个新的序列发生器 .. container:: refsynopsisdiv .. rubric:: 大纲 :name: 大纲 .. code:: synopsis 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 } ] .. container:: refsect1 :name: id-1.9.3.81.5 .. rubric:: 描述 :name: 描述 ``CREATE SEQUENCE``\ 创建一个新的序列数 发生器。这涉及到用名称\ *``name``*\ 创建并且初始化 一个新的特殊的单行表。该发生器将由发出该命令的用户所拥有。 如果给出一个模式名称,则该序列将将被创建在指定的模式中。否则它会被 创建在当前模式中。临时序列存在于一个特殊的模式中,因此在创建临时序列 时不能给出模式名。序列名称必须与同一模式中任何其他序列、表、索引、 视图或者外部表的名称不同。 在序列被创建后,可以使用函数 ``nextval``\ 、 ``currval``\ 以及 ``setval``\ 来操作该序列。 尽管无法直接更新一个序列,可以使用这样的查询: .. code:: programlisting SELECT * FROM name; 来检查一个序列的参数以及当前状态。特别地,序列的 ``last_value``\ 域显示被任意会话最后一次取得的值(当然, 在被打印时该值可能已经过时了,因为可能有其他会话正在执行 ``nextval``\ 调用)。 .. container:: refsect1 :name: id-1.9.3.81.6 .. rubric:: 参数 :name: 参数 .. container:: variablelist ``TEMPORARY`` or ``TEMP`` 如果被指定,只会为这个会话创建序列对象,并且在会话退出时自动 删除它。当临时序列存在时,已有的同名永久序列(在这个会话中) 会变得不可见,不过可以用模式限定的名称来引用同名永久序列。 ``IF NOT EXISTS`` 如果已经存在一个同名的关系时不要抛出错误。这种情况下会发出一个 提示。注意这不保证现有的关系与即将创建的序列相似 -- 它甚至可能 都不是一个序列。 *``name``* 要创建的序列的名称(可以是模式限定的)。 *``data_type``* 可选的子句\ ``AS data_type`` 制定序列的数据类型。有效类型是 ``smallint``\ 、\ ``integer``\ 、 和\ ``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`` 允许序列从任何 地方开始。对于上升序列和下降序列来说,默认的开始值分别是 *``minvalue``*\ 和 *``maxvalue``*\ 。 *``cache``* 可选的子句\ ``CACHE cache``\ 指定要预分配多少 个序列数并且把它们放在内存中以便快速访问。最小值为 1 (一次只生成 一个值,即没有缓存),默认值也是 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``\ 指定该序列不与某个列关联。 .. container:: refsect1 :name: id-1.9.3.81.7 .. rubric:: 注解 :name: 注解 使用\ ``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``\ 将不会通知 其他会话,直到它们用尽了任何已缓存的预分配值。 .. container:: refsect1 :name: id-1.9.3.81.8 .. rubric:: 示例 :name: 示例 创建一个称作\ ``serial``\ 的上升序列,从 101 开始: .. code:: programlisting CREATE SEQUENCE serial START 101; 从这个序列中选取下一个数字: .. code:: programlisting SELECT nextval('serial'); nextval --------- 101 再从这个序列中选取下一个数字: .. code:: programlisting SELECT nextval('serial'); nextval --------- 102 在一个\ ``INSERT``\ 命令中使用这个序列: .. code:: programlisting INSERT INTO distributors VALUES (nextval('serial'), 'nothing'); 在一次\ ``COPY FROM``\ 后更新新列值: .. code:: programlisting BEGIN; COPY distributors FROM 'input_file'; SELECT setval('serial', max(id)) FROM distributors; END; .. container:: refsect1 :name: id-1.9.3.81.9 .. rubric:: 兼容性 :name: 兼容性 ``CREATE SEQUENCE``\ 符合SQL 标准,不过下列除外: .. container:: itemizedlist - 使用\ ``nextval()``\ 而不是标准的\ ``NEXT VALUE FOR`` 表达式获取下一个值。 - ``OWNED BY``\ 子句是一种 OushuDB 扩展。 .. container:: refsect1 :name: id-1.9.3.81.10 .. rubric:: 另见 :name: 另见 `ALTER SEQUENCE `__, `DROP SEQUENCE `__