Sequence(序列)是数据库系统的特性,有的数据库实现了序列,有的则没有。比如Oracle、DB2、PostgreSQL数据库实现序列,MySQL、SQL Server、Sybase等数据库没有序列,序列是数据中一个特殊存放等差数列的表,该表受数据库系统控制,任何时候数据库系统都可以根据当前记录数大小加上步长来获取到该表下一条记录应该是多少,这个表没有实际意义,常常用来做主键用。不过各个数据库厂商没有一个统一的标准,各有各的一套对序列的定义和操作。本文是以Oracle数据库为例进行序列的创建、使用、案例以及注意事项的总结。
序列的创建
创建语法
CREATE SEQUENCE 序列名称 [参数]
参数说明
INCREMENT BY :序列变化的步长,负值表示递减。(默认1)
START WITH:序列的初始值 (默认1)
MINVALUE:序列可生成的最小值。(默认不限制最小值,NOMINVALUE)
MAXVALUE:序列可生成的最大值。(默认不限制最大值,NOMAXVALUE)
CYCLE:用于定义当序列产生的值达到限制值后是否循环(NOCYCLE:不循环,CYCLE:循环)。
CACHE:表示缓存序列的个数,数据库异常终止可能会导致序列中断不连续的情况,默认值为20,如果不使用缓存可设置NOCACHE
创建案例
-- Create sequence
create sequence SEQ_CREATE_NUM_ID
increment by 1
start with 1
minvalue 1
maxvalue 9999999999
nocycle
nocache;
序列的使用
currval 表示序列的当前值,新序列必须使用一次nextval 才能获取到值,否则会报ORA-08002错【参看注意事项】
查看当前序列值是多少:
select SEQ_CREATE_NUM_ID.CURRVAL from dual;
nextval 表示序列的下一个值。新序列首次使用时获取的是该序列的初始值,从第二次使用时开始按照设置的步进递增
查看序列的下一个值是多少:
select SEQ_CREATE_NUM_ID.NEXTVAL from dual;
SQL语句中使用:
insert into TABLE_NAME (id) values (SEQ_CREATE_NUM_ID.NEXTVAL);
查看已经创建的序列:
select * from user_sequences;
序列的案例
根据客户需求招聘会信息上报模块中招聘会编码要求唯一并且需要从0000000001,0000000002样的方式递增,如下图所示:
在这里只贴出Mapper.xml文件以及Service实现层部分代码。
Mapper.xml
<select id="getCreateNumId" resultType="int">
SELECT SEQ_CREATE_NUM_ID.NEXTVAL FROM dual
</select>
ServiceImpl 层
@Override
public boolean addRes(RecruitmentInfo entity) throws Exception {
//获取序列ID(形如:123)
int idNum = baseMapper.getCreateNumId();
//位数不够前补0 补到10位(形如:0000000123)
String idStr = String.format("%010d", idNum);
entity.setId(idStr);
return this.insert(entity);
}
注意事项
【注1】CURRVAL 总是返回当前序列的值,但是在第一次NEXTVAL初始化之后才能使用CURRVAL,否则会出错【ORA-08002】。
【注2】第一次NEXTVAL返回的是初始值;随后的NEXTVAL会自动增加你定义的INCREMENT BY值,然后返回增加后的值。
【注3】一次NEXTVAL会增加一次序列的值,但是如果你在同一个SQL语句里面针对同一个序列使用多次NEXTVAL,其值都是一样的。
【注4】有没有考虑过一个SQL语句中同时使用CURRVAL 和 NEXTVAL 是什么样子的呢?好奇心驱使我尝试了一下,结果两者具有相同值:
CURRVAL在前,NEXTVAL在后
--CURRVAL在前,NEXTVAL在后
select SEQ_CREATE_NUM_ID.CURRVAL,SEQ_CREATE_NUM_ID.NEXTVAL from dual;
NEXTVAL在前,CURRVAL在后
--NEXTVAL在前,CURRVAL在后
select SEQ_CREATE_NUM_ID.NEXTVAL,SEQ_CREATE_NUM_ID.CURRVAL from dual;
【注5】如果指定CACHE值,ORACLE就可以预先在内存里面放置一些序列值,这样存取的快些。cache里面的取完后,oracle自动再取一组到cache。 使用cache或许会跳号,比如数据库突然不正常down掉(shutdown abort),cache中的sequence就会丢失. 所以可以在create sequence的时候用nocache可以防止这种情况发生。