Oracle数据库里序列SEQUENCE到底怎么用,细节和技巧全解析
- 问答
- 2026-01-17 20:25:05
- 4
序列是Oracle数据库中一个独立的数据库对象,它的主要作用就是自动生成一连串唯一的数字,这些数字通常用于为表的主键列提供值,这样我们就不用费心去自己管理主键的唯一性了,非常方便,引用自Oracle官方文档对序列的基本定义。
创建一个序列最基本的语法是 CREATE SEQUENCE sequence_name;,但这样会用光所有的默认设置,为了更贴合实际需求,我们通常会指定一些参数,一个更完整的创建语句看起来是这样的:
CREATE SEQUENCE seq_employee_id
START WITH 1000 -- 从1000开始计数
INCREMENT BY 1 -- 每次增加1
NOMAXVALUE -- 没有最大值限制(默认)
NOCACHE -- 不缓存序列号
NOCYCLE; -- 不循环,达到最大值后报错停止
这里就涉及到几个核心参数,我们来详细拆解一下:
- START WITH:指定序列开始的第一个数字,默认是1。
- INCREMENT BY:指定每次递增的步长,可以是正数(递增),也可以是负数(递减),默认是1。
- MAXVALUE/NOMAXVALUE:序列能到达的最大值。
NOMAXVALUE是默认选项,对于递增序列,最大值是10的27次方;对于递减序列,最大值是-1。 - MINVALUE/NOMINVALUE:序列能到达的最小值。
- CYCLE/NOCYCLE:当序列达到最大值(或最小值)后,是否重新开始循环。
NOCYCLE是默认选项,意味着用完就报错,不会循环。 - CACHE/NOCACHE:这是非常重要的一个性能参数。
CACHE 20表示数据库一次性在内存中获取20个序列值,这样应用需要下一个序列值时,可以直接从内存拿,非常快,用完之后再一次性取下一批20个,这大大减少了磁盘I/O,提升了性能,默认是缓存20个,但有个缺点:如果数据库突然宕机,内存中缓存的但还没被使用的序列值就会“丢失”,导致序列号出现不连续的空洞。NOCACHE则能保证连续性,但性能有损耗。
创建好序列后,如何在SQL中使用它呢?主要通过两个“伪列”:
- NEXTVAL:这是最常用的,它获取序列的下一个值,并且一旦被获取,这个值就被“消耗”掉了,序列会指向下一个值。
INSERT INTO employees (id, name) VALUES (seq_employee_id.NEXTVAL, '张三');这条语句就会将序列的下一个值(比如1000)插入到id字段中。 - CURRVAL:它返回当前会话最近一次使用
NEXTVAL获取到的序列值。关键点是:你必须在当前会话中先调用过一次NEXTVAL,才能调用CURRVAL,否则会报错,它不会改变序列的当前值,它的一个常见用途是,在插入主表后,需要将同一个序列值作为外键插入到子表时使用。
接下来是一些实用的技巧和需要注意的细节,这些在实际开发中非常关键:
技巧1:关于序列值的“空洞”(Gaps)
序列号不连续是正常现象,不要依赖序列的连续性,除了之前提到的CACHE机制可能导致空洞外,还有几个常见原因:事务回滚(你用了NEXTVAL拿到了一个值,但事务回滚了,这个序列值不会被“退回”)、数据库重启(即使用了NOCACHE,在RAC环境下也可能出现)、以及一个序列被多个表共用时。
技巧2:在SELECT语句中直接使用序列
你可以通过 SELECT seq_employee_id.NEXTVAL FROM DUAL; 来简单地获取下一个序列值,这在测试或者某些需要先获取一个ID再使用的场景下很方便。
技巧3:查看序列信息
可以通过查询数据字典视图 USER_SEQUENCES 来查看你拥有的所有序列的当前状态和参数设置。SELECT sequence_name, last_number FROM USER_SEQUENCES;,这里的 last_number 是已经缓存的最后一个号码(如果用了CACHE),所以它可能比当前实际用到的最新值要大。
技巧4:修改和删除序列
你可以使用 ALTER SEQUENCE 语句来修改序列的未来行为,比如修改 INCREMENT BY、CACHE值等。你不能修改当前值(CURRVAL),如果想改变起始点,通常的做法是删除(DROP SEQUENCE)后重建,或者通过一些变通方法(如设置一个负的INCREMENT BY消耗掉一些值)。
技巧5:CACHE大小设置权衡
在高并发插入的场景下,设置一个较大的CACHE值(比如1000)可以显著提升性能,因为它减少了序列争用,但代价是序列号空洞会更大,你需要根据业务对性能和不连续性的容忍度来做权衡。
一个重要的限制:你不能在查询的子查询、视图定义、带有DISTINCT、GROUP BY、ORDER BY的语句中直接使用NEXTVAL和CURRVAL,在UPDATE语句的SET子句中和INSERT语句的VALUES子句中是可以使用的,但在一条SQL语句中所有被引用的序列,其NEXTVAL只会被计算一次,引用自Oracle官方文档对序列使用限制的说明。
序列是一个独立的对象,它并不“属于”任何一张表,你可以设计一个序列专供一张表使用,也可以让多个表共用一个序列来生成主键,但这通常不是好的设计,因为会使数据模型变得难以理解,最佳实践还是建议为每个需要代理主键的表创建专属的序列。
希望这些细节和技巧能帮助你全面理解和使用Oracle序列。

本文由雪和泽于2026-01-17发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://www.haoid.cn/wenda/82615.html
