在Oracle数据库中,序列号是一种独立的数据库对象,专门用于生成唯一的数值序列,常用于为表的主键或其他需要唯一标识的字段提供自增数值,不需要依赖应用层逻辑处理序号生成,能有效避免多会话并发时的序号冲突问题。

创建Oracle序列的基本语法
创建序列使用CREATE SEQUENCE语句,完整语法结构如下:
CREATE SEQUENCE 序列名称 [INCREMENT BY n] -- 每次递增的步长,默认是1,n可以是负整数表示递减 [START WITH n] -- 序列起始值,默认是1 [MAXVALUE n | NOMAXVALUE] -- 序列最大值,NOMAXVALUE表示不设置上限,默认是NOMAXVALUE [MINVALUE n | NOMINVALUE] -- 序列最小值,NOMINVALUE表示不设置下限,默认是NOMINVALUE [CYCLE | NOCYCLE] -- 达到极值后是否循环,NOCYCLE表示不循环,默认是NOCYCLE [CACHE n | NOCACHE] -- 预分配并缓存的序列值个数,默认是20,NOCACHE表示不缓存
创建序列示例
比如我们需要为员工表的主键生成从100开始的递增序列,每次增加1,不设置上限,不循环,缓存20个值,创建语句如下:
CREATE SEQUENCE seq_emp_id INCREMENT BY 1 START WITH 100 NOMAXVALUE NOMINVALUE NOCYCLE CACHE 20;
序列的核心属性及用法
序列创建完成后,有两个核心属性用于获取序列值:
- NEXTVAL:首次调用时返回序列的起始值,之后每次调用都会按照步长生成下一个序列值,每调用一次序列值就会递增一次。
- CURRVAL:返回当前会话最后一次调用NEXTVAL得到的序列值,在同一个会话中,必须至少调用一次NEXTVAL之后才能使用CURRVAL,否则会报错。
在SQL语句中使用序列
最常见的场景是在插入数据时,用序列值填充主键字段:
-- 插入员工数据,主键使用seq_emp_id序列的下一个值 INSERT INTO employees (emp_id, emp_name, dept_id) VALUES (seq_emp_id.NEXTVAL, '张三', 10); -- 再次插入另一条数据,序列值会自动递增 INSERT INTO employees (emp_id, emp_name, dept_id) VALUES (seq_emp_id.NEXTVAL, '李四', 20);
在PL/SQL块中使用序列
也可以在PL/SQL逻辑中获取序列值并赋值给变量使用:
DECLARE v_emp_id NUMBER; BEGIN -- 获取序列的下一个值赋值给变量 SELECT seq_emp_id.NEXTVAL INTO v_emp_id FROM dual; -- 使用变量进行后续操作 INSERT INTO employees (emp_id, emp_name, dept_id) VALUES (v_emp_id, '王五', 30); COMMIT; END; /
查询当前序列值
如果需要查看当前会话下序列的当前值,可以使用CURRVAL属性:
SELECT seq_emp_id.CURRVAL FROM dual;
使用序列的常见注意事项
- 不同会话调用NEXTVAL会各自获取独立的序列值,不会出现冲突,但序列值不一定完全连续,因为缓存机制或者事务回滚可能导致部分序列值未被使用。
- 如果序列设置了CYCLE属性,当到达最大值后,会重新从最小值开始生成,这时候需要保证生成的值不会和已有的主键值冲突,否则插入数据时会报主键重复错误。
- 如果要修改序列的参数,可以使用
ALTER SEQUENCE语句,但是不能修改序列的起始值,如果需要修改起始值,只能先删除序列再重新创建。 - 删除序列使用
DROP SEQUENCE 序列名称语句,删除后序列无法恢复,需要谨慎操作。