序列号SEQUENCE:是Oracle提供的用于产生一系列唯一数字的数据库对象。
序列号在数据库中是一个共享对象,序列号是一个计数器,它并不会与特定的表关联。
主要用于提供主键值或唯一约束值。
将序列值装入内存可以提高访问效率。
创建序列号语法:
CREATE SEQUENCE [SCHEMA.]SEQUENCE_NAME
[INCREMENT BY N]
[START WITH N]
[{MAXVALUE N | NOMAXVALUE}]
[{MINVALUE N | NOMINVALUE}]
[{CYCLE | NOCYCLE}]
[{CACHE N | NOCACHE}];
SEQUENCE_NAME:序列号名称
INCREMENT BY用于定义序列的步长,如果省略,则默认为1,如果出现负值,则代表Oracle序列的值是按照此步长递减的。
START WITH 定义序列的初始值(即产生的第一个值),默认为1。
MAXVALUE 定义序列生成器能产生的最大值。选项NOMAXVALUE是默认选项,代表没有最大值定义,这时对于递增Oracle序列,系统能够产生的最大值是10的27次方;对于递减序列,最大值是-1。
MINVALUE定义序列生成器能产生的最小值。选项NOMAXVALUE是默认选项,代表没有最小值定义,这时对于递减序列,系统能够产生的最小值是-10的26次方;对于递增序列,最小值是1。
CYCLE和NOCYCLE 表示当序列生成器的值达到限制值后是否循环。CYCLE代表循环,NOCYCLE代表不循环。如果循环,则当递增序列达到最大值时,循环到最小值;最小值为1。对于递减序列达到最小值时,循环到最大值。如果不循环,达到限制值后,继续产生新值就会发生错误。
CACHE(缓冲)定义存放序列的内存块的大小,默认为20。NOCACHE表示不对序列进行内存缓冲。对序列进行内存缓冲,可以改善序列的性能。 缓存选项会造成数据丢失,当实例异常关闭时。
如果指定CACHE值,ORACLE就可以预先在内存里面放置一些SEQUENCE,这样存取的快些。CACHE里面的取完后,ORACLE自动再取一组到CACHE。使用CACHE或许会跳号, 比如数据库突然不正常DOWN掉(SHUTDOWN ABORT),CACHE中的SEQUENCE就会丢失。举个例子:比如你的SEQUENCE中CACHE 100,那当你SEQUENCE取到90时突然断电,那么在你重启数据库后,SEQUENCE的值将从101开始。
如果指定NOCACHE值,ORACLE就不会预先在内存里面存放SEQUENCE,当然这也就可以避免数据库不正常DOWN掉的SEQUENCE丢失。不过会产生一些问题:创建NOCACHE SEQUENCE在高并发访问时,容易导致ROW CACHE LOCK等待事件,主要原因是每次获取NEXTVAL时都需要修改ROWCACHE中的字典信息。使用NOCACHE SEQUENCE,还会导致如下问题:
由于每次修改字典信息都需要COMMIT,可能导致LOG FILE SYNC等待,NOCACHE SEQUENCE在RAC环境下,会对基于SEQUENCE生成的列创建的索引,造成实例间大量索引块争用,基于以上问题,避免创建NOCACHE SEQUENCE。
SEQUENCE相关保护机制:
ROW CACHE LOCK:在调用SEQUENCE.NEXTVAL情况下需要修改数据字典时发生,对应ROW CACHE LOCK事件。
SQ LOCK:在内存缓存(并非ROW CACHE)上获取SEQUENCE.NEXTVAL时发生,对应ENQ:SQ-CONTENTION事件。
SV LOCK:RAC环境下获取CACHE+ORDER属性的SEQUENCE.NEXTVAL时发生,对应DFS LOCK HANDLE事件。
使用序列号会产生跳号,序列在下列情况下出现裂缝:
回滚
系统异常
多个表同时使用同一序列
序列号使用:
-- 返回序列中下一个有效的值,任何用户都可以引用
SELECT SEQUENCE_NAME.NEXTVAL FROM DUAL;
-- 序列的当前值
SELECT SEQUENCE_NAME.CURRVAL FROM DUAL;
实例应用:实现ID的自动递增
创建序列号
CREATE SEQUENCE TEST_SEQ INCREMENT BY 1 START WITH 1 MAXVALUE 30000 MINVALUE 1
CACHE 2;
创建表
CREATE TABLE TEST_TABLE(
ID NUMBER(6),
NAME VARCHAR2(30),courier; font-size: 14px;">CONSTRAINT PK_ID PRIMARY KEY(ID)
);
插入数据
INSERT INTO TEST_TABLE VALUES(TEST_SEQ.NEXTVAL,'TOM');
COMMIT;
查看数据库中的序列号:
SELECT * FROM USER_SEQUENCES;
SELECT * FROM ALL_SEQUENCES;
SELECT * FROM DBA_SEQUENCES;
修改序列号:
ALTER SEQUENCE SEQUENCE_NAME
[{CACHE N | NOCACHE}];
不能修改序列的初始值,否则会报ORA-02283:无法更改启动序列号
删除序列号:
DROP SEQUENCE [SCHEMA.]序列名;