[目录]
参考
Oracle 序列
什么是序列
数据库对象的一种。通过序列生成连续的数字以此来实现主键字段的自己主动、唯一增长,而且一个序列可为多列、多表同一时候使用。
创建一个简单序列
例子:
--创建序列create sequence seq_test --创建一个序列minvalue 1 --最小值maxvalue 100000 --最大值start with 1 --指定序列起始数increment by 1 --指定序列增长步长cache 20 --指定数据库内存中预分配的序列值个数,以便高速获取。最小cache值为2
测试序列
--测试序列select seq_test.nextval as 下一个值 from dual;select seq_test.currval as 当前值 from dual
创建语法说明
increment by:指定序列增长步长。能够为正(升序)、负整数(降序)。但不能为0。最高精度28。
start with: 指定序列起始数。默觉得序列最小值。
maxvalue :指定序列最大值。最大28位。必须大于等于起始值且大于等于序列最小值。
nomaxvalue 无最大值(实际为10^27或-1)。默认。
minvalue :指定序列最小值。
nominvalue :无最小值(实际为1或-10^26)。默认。
cycle :指定序列达到最大值或最小值后继续从头开始生成。带有cycle条件序列当达到最大值后,下一个值从最小值 minvalue 开始循环!
例子:
create sequence seq_test --创建一个序列minvalue 1 --最小值maxvalue 100000 --最大值start with 1 --指定序列起始数increment by 1 --指定序列增长步长cycle --指定序列达到最大值或最小值后继续从头开始生成cache 20 --指定数据库内存中预分配的序列值个数,以便高速获取。最小cache值为2
nocycle :不循环生成。默认。
cache :指定数据库内存中预分配的序列值个数,以便高速获取。最小 cache 值为2。假设系统发生问题。全部缓存的没有被 DML 语句使用并提交的序列值将丢失。潜在丢失值数量等于 cache 的数量。cache 参数最大值为:(cell(maxvalue - minvalue)) / abs(increment)
nocache :不指定缓存数,默认缓存20。
order :指定 order 条件保证序列按请求顺序生成。
此条件适用于 rac 环境。
noorder :不保证序列按请求顺序生成。
授权序列
grant select on seq_test to luoma with grant option;grant select on seq_test to luoma;
修改语法说明
语法说明:
1.想以不同的数字又一次开始序列,必须删除重建
例如上面创建的例子中的序列修改为 55:
alter sequence seq_test start with 55 --修改序列起始数
执行提示:
ORA-02293:无法变更启动序列号
2.改动的 maxvalue 必须大于序列当前值
例如:
alter sequence seq_test maxvalue 1 --修改序列最大值
执行提示:
ORA-04004:MINVALUE 必须小于 MAXVALUE
删除语法说明
例子:
drop sequence seq_test--删除序列
手动序列
案例:客户化系统单据序列操作的 API
序列对应表-COMMON_DOC_SEQUENCES
-- Create tablecreate table COMMON_DOC_SEQUENCES(doc_type VARCHAR2(45) not null,pk1_value VARCHAR2(50) not null,pk2_value VARCHAR2(50),pk3_value VARCHAR2(50),pk4_value VARCHAR2(75),pk5_value VARCHAR2(50),next_seq_number NUMBER,created_by NUMBER not null,creation_date DATE not null,last_updated_by NUMBER not null,last_update_date DATE not null,last_update_login NUMBER);-- Create/Recreate indexescreate unique index COMMON_DOC_SEQUENCES_N1 on COMMON_DOC_SEQUENCES (DOC_TYPE, PK1_VALUE, PK2_VALUE, PK3_VALUE, PK4_VALUE, PK5_VALUE);
序列对应包
CREATE OR REPLACE PACKAGE "COMMON_DOC_SEQUENCE_UTL" AS/*==================================================Program Name:COMMON_DOC_SEQUENCE_UTLDescription:该程序包提供客户化系统单据序列操作的 APIHistory:==================================================*//*==================================================Function Name :next_seq_numberDescription:获取下一个单据号Argument:p_doc_type : 单据类型p_pk1_value : 主关键字1p_pk2_value : 主关键字2p_pk3_value : 主关键字3p_pk4_value : 主关键字4p_pk5_value : 主关键字5p_init_number : 初始序列号Return:NUMBER : 返回单据号序列History:==================================================*/FUNCTION next_seq_number(p_doc_type IN VARCHAR2,p_pk1_value IN VARCHAR2 DEFAULT NULL,p_pk2_value IN VARCHAR2 DEFAULT NULL,p_pk3_value IN VARCHAR2 DEFAULT NULL,p_pk4_value IN VARCHAR2 DEFAULT NULL,p_pk5_value IN VARCHAR2 DEFAULT NULL,p_init_number IN NUMBER DEFAULT 1) RETURN NUMBER;/*==================================================Function Name :next_seq_numberDescription:获取下一个单据号Argument:p_doc_type : 单据类型p_doc_prefix :前缀p_seq_length : 长度p_pk1_value : 主关键字1p_pk2_value : 主关键字2p_pk3_value : 主关键字3p_pk4_value : 主关键字4p_pk5_value : 主关键字5p_init_number : 初始序列号Return:VARCHAR2 : 返回单据号History:==================================================*/FUNCTION next_seq_number(p_doc_type IN VARCHAR2,p_doc_prefix IN VARCHAR2,p_seq_length IN NUMBER DEFAULT 0,p_pk1_value IN VARCHAR2 DEFAULT NULL,p_pk2_value IN VARCHAR2 DEFAULT NULL,p_pk3_value IN VARCHAR2 DEFAULT NULL,p_pk4_value IN VARCHAR2 DEFAULT NULL,p_pk5_value IN VARCHAR2 DEFAULT NULL,p_init_number IN NUMBER DEFAULT 1) RETURN VARCHAR2;/*==================================================Function Name :next_seq_numberDescription:获取当前单据号Argument:p_doc_type : 单据类型p_doc_prefix :前缀p_seq_length : 长度p_pk1_value : 主关键字1p_pk2_value : 主关键字2p_pk3_value : 主关键字3p_pk4_value : 主关键字4p_pk5_value : 主关键字5p_init_number : 初始序列号Return:VARCHAR2 : 返回单据号History:==================================================*/FUNCTION curr_seq_number(p_doc_type IN VARCHAR2,p_doc_prefix IN VARCHAR2,p_seq_length IN NUMBER DEFAULT 0,p_pk1_value IN VARCHAR2 DEFAULT NULL,p_pk2_value IN VARCHAR2 DEFAULT NULL,p_pk3_value IN VARCHAR2 DEFAULT NULL,p_pk4_value IN VARCHAR2 DEFAULT NULL,p_pk5_value IN VARCHAR2 DEFAULT NULL,p_init_number IN NUMBER DEFAULT 1) RETURN VARCHAR2;END COMMON_DOC_SEQUENCE_UTL;/CREATE OR REPLACE PACKAGE BODY "COMMON_DOC_SEQUENCE_UTL" AS/*==================================================Program Name:COMMONDescription:该程序包提供客户化系统单据序列操作的APIHistory:==================================================*/FUNCTION next_seq_number(p_doc_type IN VARCHAR2,p_pk1_value IN VARCHAR2 DEFAULT NULL,p_pk2_value IN VARCHAR2 DEFAULT NULL,p_pk3_value IN VARCHAR2 DEFAULT NULL,p_pk4_value IN VARCHAR2 DEFAULT NULL,p_pk5_value IN VARCHAR2 DEFAULT NULL,p_init_number IN NUMBER DEFAULT 1) RETURN NUMBER ISPRAGMA AUTONOMOUS_TRANSACTION;l_doc_type VARCHAR2(30);CURSOR c_seq_del ISSELECT *FROM (SELECT ds.rowid row_id,ds.next_seq_numberFROM COMMON_DOC_SEQUENCES dsWHERE ds.doc_type = l_doc_typeAND ds.pk1_value = nvl(p_pk1_value, '-1')AND ds.pk2_value = nvl(p_pk2_value, '-1')AND ds.pk3_value = nvl(p_pk3_value, '-1')AND ds.pk4_value = nvl(p_pk4_value, '-1')AND ds.pk5_value = nvl(p_pk5_value, '-1')ORDER BY ds.next_seq_number) ttWHERE rownum = 1;CURSOR c_seq ISSELECT ds.rowid row_id,ds.next_seq_numberFROM COMMON_DOC_SEQUENCES dsWHERE ds.doc_type = p_doc_typeAND ds.pk1_value = nvl(p_pk1_value, '-1')AND ds.pk2_value = nvl(p_pk2_value, '-1')AND ds.pk3_value = nvl(p_pk3_value, '-1')AND ds.pk4_value = nvl(p_pk4_value, '-1')AND ds.pk5_value = nvl(p_pk5_value, '-1')FOR UPDATE; -- NOWAIT;l_row_id VARCHAR2(18);l_next_seq_number NUMBER;BEGINl_doc_type := p_doc_type || 'DEL';--先看是否存在删除的数据OPEN c_seq_del;FETCH c_seq_delINTO l_row_id,l_next_seq_number;IF c_seq_del%NOTFOUND THEN--不存在断号OPEN c_seq;FETCH c_seqINTO l_row_id,l_next_seq_number;IF c_seq%NOTFOUND THENl_next_seq_number := nvl(p_init_number, 1);INSERT INTO COMMON_DOC_SEQUENCES(doc_type,pk1_value,pk2_value,pk3_value,pk4_value,pk5_value,next_seq_number,creation_date,created_by,last_update_date,last_updated_by,last_update_login)VALUES(p_doc_type,nvl(p_pk1_value, '-1'),nvl(p_pk2_value, '-1'),nvl(p_pk3_value, '-1'),nvl(p_pk4_value, '-1'),nvl(p_pk5_value, '-1'),l_next_seq_number,SYSDATE,1,SYSDATE,1,1);ELSEl_next_seq_number := l_next_seq_number + 1;UPDATE COMMON_DOC_SEQUENCESSET next_seq_number = l_next_seq_number,last_update_date = SYSDATE,last_updated_by = 1,last_update_login = 1WHERE ROWID = l_row_id;END IF;CLOSE c_seq;ELSE--用删除掉的编号DELETE FROM COMMON_DOC_SEQUENCES WHERE ROWID = l_row_id;END IF;COMMIT;RETURN l_next_seq_number;END next_seq_number;FUNCTION next_seq_number(p_doc_type IN VARCHAR2,p_doc_prefix IN VARCHAR2,p_seq_length IN NUMBER DEFAULT 0,p_pk1_value IN VARCHAR2 DEFAULT NULL,p_pk2_value IN VARCHAR2 DEFAULT NULL,p_pk3_value IN VARCHAR2 DEFAULT NULL,p_pk4_value IN VARCHAR2 DEFAULT NULL,p_pk5_value IN VARCHAR2 DEFAULT NULL,p_init_number IN NUMBER DEFAULT 1) RETURN VARCHAR2 ISl_next_seq_number NUMBER;l_doc_number VARCHAR2(150);BEGINl_next_seq_number := next_seq_number(p_doc_type => p_doc_type,p_pk1_value => p_pk1_value,p_pk2_value => p_pk2_value,p_pk3_value => p_pk3_value,p_pk4_value => p_pk4_value,p_pk5_value => p_pk5_value,p_init_number => p_init_number);IF p_seq_length IS NULL OR p_seq_length = 0 THENl_doc_number := p_doc_prefix || l_next_seq_number;ELSEIF length(l_next_seq_number) >= p_seq_length THENl_doc_number := p_doc_prefix || l_next_seq_number;ELSEl_doc_number := p_doc_prefix || lpad(l_next_seq_number, p_seq_length, '0');END IF;END IF;RETURN l_doc_number;END next_seq_number;FUNCTION curr_seq_number(p_doc_type IN VARCHAR2,p_doc_prefix IN VARCHAR2,p_seq_length IN NUMBER DEFAULT 0,p_pk1_value IN VARCHAR2 DEFAULT NULL,p_pk2_value IN VARCHAR2 DEFAULT NULL,p_pk3_value IN VARCHAR2 DEFAULT NULL,p_pk4_value IN VARCHAR2 DEFAULT NULL,p_pk5_value IN VARCHAR2 DEFAULT NULL,p_init_number IN NUMBER DEFAULT 1) RETURN VARCHAR2 ISPRAGMA AUTONOMOUS_TRANSACTION;CURSOR c_seq ISSELECT ds.rowid row_id,ds.next_seq_numberFROM COMMON_DOC_SEQUENCES dsWHERE ds.doc_type = p_doc_typeAND ds.pk1_value = nvl(p_pk1_value, '-1')AND ds.pk2_value = nvl(p_pk2_value, '-1')AND ds.pk3_value = nvl(p_pk3_value, '-1')AND ds.pk4_value = nvl(p_pk4_value, '-1')AND ds.pk5_value = nvl(p_pk5_value, '-1')FOR UPDATE; -- NOWAIT;l_row_id VARCHAR2(18);l_next_seq_number NUMBER;BEGINOPEN c_seq;FETCH c_seqINTO l_row_id,l_next_seq_number;IF c_seq%NOTFOUND THENl_next_seq_number := next_seq_number(p_doc_type => p_doc_type,p_doc_prefix => NULL,p_seq_length => p_seq_length,p_pk1_value => p_pk1_value,p_pk2_value => NULL,p_pk3_value => NULL,p_pk4_value => NULL,p_pk5_value => NULL,p_init_number => 1);INSERT INTO COMMON_DOC_SEQUENCES(doc_type,pk1_value,pk2_value,pk3_value,pk4_value,pk5_value,next_seq_number,creation_date,created_by,last_update_date,last_updated_by,last_update_login)VALUES(p_doc_type,nvl(p_pk1_value, '-1'),nvl(p_pk2_value, '-1'),nvl(p_pk3_value, '-1'),nvl(p_pk4_value, '-1'),nvl(p_pk5_value, '-1'),l_next_seq_number,SYSDATE,1,SYSDATE,1,1);END IF;IF p_seq_length IS NULL OR p_seq_length = 0 THENl_next_seq_number := p_doc_prefix || l_next_seq_number;ELSEIF length(l_next_seq_number) >= p_seq_length THENl_next_seq_number := p_doc_prefix || l_next_seq_number;ELSEl_next_seq_number := p_doc_prefix || lpad(l_next_seq_number, p_seq_length, '0');END IF;END IF;CLOSE c_seq;COMMIT;RETURN l_next_seq_number;END curr_seq_number;END COMMON_DOC_SEQUENCE_UTL;/
使用案例
--流水号获取declarevar_no number;var_no_str varchar2(100);begin--单独的号码var_no := COMMON_DOC_SEQUENCE_UTL.next_seq_number('PAYMENT_WRITE_OFF','BATCHID-INVOICE_NO_NUMBER','','','','',1);dbms_output.put_line(var_no);--带数量的前缀var_no_str := COMMON_DOC_SEQUENCE_UTL.next_seq_number('PAYMENT_WRITE_OFF','-',3,'BATCHID-SAVEPREPAYAPPLYDATA','','','','',1);dbms_output.put_line(var_no_str);end;
第一次调用
1-001
第二次调用
2-002
查询生成结果
--验证select t.*,t.rowidfrom common_doc_sequences twhere doc_type = 'PAYMENT_WRITE_OFF'