Skip to content

DB2 - 序列

本章涵盖了序列(Sequences),这是一种现代且高性能的方法,用于为主键、订单号等生成唯一的数字标识符。

序列是数据库对象,它生成一系列唯一的数字(例如,1、2、3…)。它不与任何特定表绑定,因此非常灵活。序列是生成替代主键(surrogate primary keys)的理想选择,因为它们是事务安全的、高并发的且性能良好。

序列与 IDENTITY 列: IDENTITY 列是表列的一个属性,在插入时自动生成值。SEQUENCE 是一个独立的数据库对象。对于简单、单表主键,请使用 IDENTITY 列。当您需要在多个表之间共享相同的数字系列或需要对其属性进行更多控制时,请使用 SEQUENCE。

CREATE SEQUENCE 语句提供了许多选项来自定义其行为。

-- 通用语法
CREATE SEQUENCE <sequence_name>
AS <data_type> -- 例如,BIGINT, INTEGER
START WITH <number> -- 起始值
INCREMENT BY <number> -- 每次增加的值
MINVALUE <number> -- 最小值
MAXVALUE <number> -- 最大值
[ CYCLE | NO CYCLE ] -- 达到 MAXVALUE 时是否重启?
[ CACHE <number> | NO CACHE ]; -- 为性能预分配值
-- 实际示例:用于生成订单 ID 的序列
CREATE SEQUENCE ORDER_ID_SEQ
AS BIGINT -- 使用 BIGINT 防止数字用尽
START WITH 1000 -- 从 1000 开始编号
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
NO CYCLE -- 对于主键至关重要!
CACHE 20; -- 在内存中预分配 20 个数字以实现快速访问

最佳实践: 对于生成主键的序列,始终使用 NO CYCLE。循环可能导致非唯一值。CACHE 选项显著提高了性能,但如果系统重启,可能会导致数字序列中出现空缺,这对于替代键通常是可以接受的。

您可以使用 NEXT VALUE FOR 和 PREVIOUS VALUE FOR 表达式与序列进行交互。

  • NEXT VALUE FOR <sequence_name>: 原子性地从序列中获取下一个数字。这是最常见的操作。
  • PREVIOUS VALUE FOR <sequence_name>: 返回您当前会话中由 NEXT VALUE 生成的最新值。它不显示全局生成的最后一个值。

最常见的用例是在 INSERT 语句中。

-- 创建一个示例订单表
CREATE TABLE ORDERS (
ORDER_ID BIGINT NOT NULL PRIMARY KEY,
CUSTOMER_ID INT NOT NULL,
ORDER_DATE DATE NOT NULL DEFAULT CURRENT_DATE
);
-- 使用序列生成主键并插入新订单
INSERT INTO ORDERS (ORDER_ID, CUSTOMER_ID)
VALUES (NEXT VALUE FOR ORDER_ID_SEQ, 452);

您可以使用 ALTER SEQUENCE 在序列创建后修改其大部分属性。一个常见的任务是重新启动序列。

-- 从指定数字重新启动序列
ALTER SEQUENCE ORDER_ID_SEQ RESTART WITH 50000;

要查看序列的当前配置和状态,请查询系统目录视图 SYSCAT.SEQUENCES。

-- 获取特定序列的详细信息
SELECT SEQNAME, START, NEXTCACHEFIRSTVAL, CACHE
FROM SYSCAT.SEQUENCES
WHERE SEQNAME = 'ORDER_ID_SEQ';

要从数据库中永久删除序列,请使用 DROP SEQUENCE 命令。

DROP SEQUENCE ORDER_ID_SEQ;