项目中需要使用到按规则生成序列号,开始的解决办法是根据条件取得最大ID号进行分解+1再合并的解决方案,后来发现如果两个客户同时操作的时候出现问题:添加的时候ID已经存在,原因是:A用户在访问取得第MAX(N)记录deID,但是还没有进行增加操作,这时,B用户也取得第MAX(N)记录deID,这是A进行添加操作同时,B也同时进行添加操作,那么B用户就会保存失败,我们开始的时候采用的解决方案是
:(枷锁)在程序的方法上枷锁,采用单线程操作,实施结果:失败,客户等待时间长,后来我们采用绑定数据库的方案:编写存储过程,虽然绑定不怎么方便,但是执行效率要快很多。由于时间问题,没有做序列自动创建功能,欢迎各位大虾进行指点和评论,我们最后的方案如下:
在oracle里面编写了2个基本做基本处理的自定义函数:
create or replace function fun_config_glide_num(p_class  varchar2,
                                                p_column varchar2)
/**
  * 流水帐号配置_oracle
  * author:ai bo 2010.02.23
  *  p_table varchar2 表名
  *  p_website varchar2 自定义开头字符
  */
 return varchar2 as
  v_curId integer;
  --  v_seq       varchar2(50);
  -- v_seq_value number;
  v_sql     varchar2(200);
  v_ret     number(3);
  v_num     varchar2(20);
  p_table   varchar2(30);
  p_website varchar2(20);
  p_length  varchar2(3);
  t_class   varchar2(20);
  t_column  varchar2(20);
begin
  t_class  := p_class;
  t_column := p_column;
  v_sql    := 'SELECT lszh_tname,lszh_mark,lszh_num FROM lszh_table WHERE lszh_cname = ' ||
              chr(39) || t_class || chr(39) || '
 and lszh_column=' || chr(39) || t_column || chr(39) || '';
  v_curId  := DBMS_SQL.OPEN_CURSOR; --为处理打开光标
  DBMS_SQL.PARSE(v_curId, v_Sql, DBMS_SQL.native); --分析语句
  DBMS_SQL.DEFINE_COLUMN(v_curId, 1, p_table, 128); --定义动态游标所能得到的对应值
  DBMS_SQL.DEFINE_COLUMN(v_curId, 2, p_website, 128);
  DBMS_SQL.DEFINE_COLUMN(v_curId, 3, p_length, 128);
  v_ret := DBMS_SQL.EXECUTE(v_curId); --执行语句
  loop
    if DBMS_SQL.FETCH_ROWS(v_curId) = 0 then
      exit;
    end if;
    DBMS_SQL.COLUMN_VALUE(v_curId, 1, p_table); --将所取得的游标数据赋值到相应的变量
    --DBMS_OUTPUT.PUT_LINE(p_table);
    DBMS_SQL.COLUMN_VALUE(v_curId, 2, p_website);
    --DBMS_OUTPUT.PUT_LINE(p_website);
    DBMS_SQL.COLUMN_VALUE(v_curId, 3, p_length);
    --DBMS_OUTPUT.PUT_LINE(p_length);
  end loop;
  DBMS_SQL.CLOSE_CURSOR(v_curid); --关闭一个动态游标
  v_num := fun_get_glide_num(trim(p_table), trim(p_website), trim(p_length));
  return v_num;
end;
create or replace function fun_get_glide_num(p_table   varchar2,p_website varchar2,p_length number)
/**
* 流水帐号创建oracle版本
* author : ai bo 2010.02.23
*  p_table varchar2 表名
*  p_website varchar2 自定义开头字符
*/
return varchar2 as
   v_seq       varchar2(50);
   v_seq_value number;
    v_sql       varchar2(200);
   v_num       varchar2(20);
begin
    v_seq := 'seq_' || p_table;
    v_sql := 'select ' || v_seq || '.nextval from dual';
    dbms_output.put_line(v_sql);
   execute immediate v_sql
       into v_seq_value;
   select lpad(v_seq_value, p_length, '0') into v_num from dual;
   v_num := p_website || v_num;
    return v_num;
end;
下面为调用实例:
 select fun_config_glide_num('TabMachineType','FAC_CODE') as CN FROM dual;
select fun_config_glide_num('TabMachineType','FAC_CODE') as CN FROM dual;
下面是表流水帐号表结构
 -- Create table
-- Create table
 create table LSZH_TABLE
create table LSZH_TABLE
 (
(
 LSZH_CNAME    CHAR(20) not null,
  LSZH_CNAME    CHAR(20) not null,
 LSZH_TNAME    CHAR(20),
  LSZH_TNAME    CHAR(20),
 LSZH_COLUMN   CHAR(20) not null,
  LSZH_COLUMN   CHAR(20) not null,
 LSZH_MARK     CHAR(20),
  LSZH_MARK     CHAR(20),
 LSZH_DATETYPE CHAR(10),
  LSZH_DATETYPE CHAR(10),
 LSZH_NUM      CHAR(3) default 4
  LSZH_NUM      CHAR(3) default 4
 )
)

 -- Add comments to the columns
-- Add comments to the columns 
 comment on column LSZH_TABLE.LSZH_CNAME
comment on column LSZH_TABLE.LSZH_CNAME
 is '流水帐号类名';
  is '流水帐号类名';
 comment on column LSZH_TABLE.LSZH_TNAME
comment on column LSZH_TABLE.LSZH_TNAME
 is '流水帐对应的数据库表名';
  is '流水帐对应的数据库表名';
 comment on column LSZH_TABLE.LSZH_COLUMN
comment on column LSZH_TABLE.LSZH_COLUMN
 is '流水帐号类别标识列';
  is '流水帐号类别标识列';
 comment on column LSZH_TABLE.LSZH_MARK
comment on column LSZH_TABLE.LSZH_MARK
 is '流水帐号类别标识对应的字符';
  is '流水帐号类别标识对应的字符';
 comment on column LSZH_TABLE.LSZH_DATETYPE
comment on column LSZH_TABLE.LSZH_DATETYPE
 is '时间作为流水号的排列次序';
  is '时间作为流水号的排列次序';
 comment on column LSZH_TABLE.LSZH_NUM
comment on column LSZH_TABLE.LSZH_NUM
 is '流水码长度';
  is '流水码长度';
 -- Create/Recreate primary, unique and foreign key constraints
-- Create/Recreate primary, unique and foreign key constraints 
 alter table LSZH_TABLE
alter table LSZH_TABLE
 add constraint PK_LSZH_TABLE primary key (LSZH_COLUMN, LSZH_CNAME)
  add constraint PK_LSZH_TABLE primary key (LSZH_COLUMN, LSZH_CNAME)

参考资料:
 DBMS_SQL系统包提供了很多函数及过程,现在简要阐述其中使用频率较高的几种:
DBMS_SQL系统包提供了很多函数及过程,现在简要阐述其中使用频率较高的几种:   
 
    
 function   open_cursor:打开一个动态游标,并返回一个整型;
  function   open_cursor:打开一个动态游标,并返回一个整型;   
 
    
 procedure   close_cursor(c   in   out   integer);关闭一个动态游标,参数为open_cursor所打开的游标;
  procedure   close_cursor(c   in   out   integer);关闭一个动态游标,参数为open_cursor所打开的游标;   
 
    
 procedure   parse(c   in   integer,   statement   in   varchar2,   language_flag   in   integer):对动态游标所提供的sql语句进行解析,参数C表示游标,statement为sql语句,language-flag为解析sql语句所用oracle版本,一般有V6,V7跟native(在不明白所连database版本时,使用native);
  procedure   parse(c   in   integer,   statement   in   varchar2,   language_flag   in   integer):对动态游标所提供的sql语句进行解析,参数C表示游标,statement为sql语句,language-flag为解析sql语句所用oracle版本,一般有V6,V7跟native(在不明白所连database版本时,使用native);   
 
    
 procedure   define_column(c   in   integer,   position   in   integer,   column   any   datatype,   [column_size   in   integer]):定义动态游标所能得到的对应值,其中c为动态游标,positon为对应动态sql中的位置(从1开始),column为该值所对应的变量,可以为任何类型,column_size只有在column为定义长度的类型中使用如VARCHAR2,CHAR等(该过程有很多种情况,此处只对一般使用到的类型进行表述);
  procedure   define_column(c   in   integer,   position   in   integer,   column   any   datatype,   [column_size   in   integer]):定义动态游标所能得到的对应值,其中c为动态游标,positon为对应动态sql中的位置(从1开始),column为该值所对应的变量,可以为任何类型,column_size只有在column为定义长度的类型中使用如VARCHAR2,CHAR等(该过程有很多种情况,此处只对一般使用到的类型进行表述);   
 
    
 function   execute(c   in   integer):执行游标,并返回处理一个整型,代表处理结果(对insert,delete,update才有意义,而对select语句而言可以忽略);
  function   execute(c   in   integer):执行游标,并返回处理一个整型,代表处理结果(对insert,delete,update才有意义,而对select语句而言可以忽略);   
 
    
 function   fetch_rows(c   in   integer):对游标进行循环取数据,并返回一个整数,为0时表示已经取到游标末端;
  function   fetch_rows(c   in   integer):对游标进行循环取数据,并返回一个整数,为0时表示已经取到游标末端;   
 
    
 procedure   column_value(c   in   integer,   position   in   integer,   value):将所取得的游标数据赋值到相应的变量,c为游标,position为位置,value则为对应的变量;
  procedure   column_value(c   in   integer,   position   in   integer,   value):将所取得的游标数据赋值到相应的变量,c为游标,position为位置,value则为对应的变量;   
 
    
 procedure   bind_variable(c   in   integer,   name   in   varchar2,   value):定义动态sql语句(DML)中所对应字段的值,c为游标,name为字段名称,value为字段的值;
  procedure   bind_variable(c   in   integer,   name   in   varchar2,   value):定义动态sql语句(DML)中所对应字段的值,c为游标,name为字段名称,value为字段的值;   
 
    
 以上是在程序中经常使用到的几个函数及过程,其他函数及过程请参照oracle所提供定义语句dbmssql.sql
  以上是在程序中经常使用到的几个函数及过程,其他函数及过程请参照oracle所提供定义语句dbmssql.sql   
 
    
 
    
 对于一般的select操作,如果使用动态的sql语句则需要进行以下几个步骤:
  对于一般的select操作,如果使用动态的sql语句则需要进行以下几个步骤:   
 open   cursor--->parse--->define   column--->excute--->fetch   rows--->close   cursor;
  open   cursor--->parse--->define   column--->excute--->fetch   rows--->close   cursor;   
 而对于dml操作(insert,update)则需要进行以下几个步骤:
  而对于dml操作(insert,update)则需要进行以下几个步骤:   
 open   cursor--->parse--->bind   variable--->execute--->close   cursor;
  open   cursor--->parse--->bind   variable--->execute--->close   cursor;   
 对于delete操作只需要进行以下几个步骤:
  对于delete操作只需要进行以下几个步骤:   
 open   cursor--->parse--->execute--->close   cursor;
  open   cursor--->parse--->execute--->close   cursor;   

 http://www.examda.com/Oracle/
http://www.examda.com/Oracle/
 关于Oracle的序列(Sequence)使用序列是一数据库对象,利用它可生成唯一的整数。一般使用序列自动地生成主键值。对我们程序员来讲,精力时间有限,我们只学最有用的知识。大家请看:
关于Oracle的序列(Sequence)使用序列是一数据库对象,利用它可生成唯一的整数。一般使用序列自动地生成主键值。对我们程序员来讲,精力时间有限,我们只学最有用的知识。大家请看:
 1) 建立序列命令
  1) 建立序列命令
 CREATE SEQUENCE [user.]sequence_name
  CREATE SEQUENCE [user.]sequence_name
 [increment by n]
  [increment by n]
 [start with n]
  [start with n]
 [maxvalue n | nomaxvalue]
  [maxvalue n | nomaxvalue]
 [minvalue n | nominvalue];
  [minvalue n | nominvalue];
 [NOCYCLE]  --
  [NOCYCLE]  --
 INCREMENT BY: 指定序列号之间的间隔,该值可为正的或负的整数,但不可为0.序列为升序。忽略该子句时,缺省值为1.
  INCREMENT BY: 指定序列号之间的间隔,该值可为正的或负的整数,但不可为0.序列为升序。忽略该子句时,缺省值为1.
 START WITH:指定生成的第一个序列号。在升序时,序列可从比最小值大的值开始,缺省值为序列的最小值。对于降序,序列可由比最大值小的值开始,缺省值为序列的最大值。
  START WITH:指定生成的第一个序列号。在升序时,序列可从比最小值大的值开始,缺省值为序列的最小值。对于降序,序列可由比最大值小的值开始,缺省值为序列的最大值。
 MAXVALUE:指定序列可生成的最大值。
  MAXVALUE:指定序列可生成的最大值。
 NOMAXVALUE:为升序指定最大值为1027,为降序指定最大值为-1.
  NOMAXVALUE:为升序指定最大值为1027,为降序指定最大值为-1.
 MINVALUE:指定序列的最小值。
  MINVALUE:指定序列的最小值。
 NOMINVALUE:为升序指定最小值为1.为降序指定最小值为-1026.
  NOMINVALUE:为升序指定最小值为1.为降序指定最小值为-1026.
 NOCYCLE:一直累加,不循环
  NOCYCLE:一直累加,不循环
 2) 更改序列命令
  2) 更改序列命令
 ALTERSEQUENCE [user.]sequence_name
  ALTERSEQUENCE [user.]sequence_name
 [INCREMENT BY n]
  [INCREMENT BY n]
 [MAXVALUE n| NOMAXVALUE ]
  [MAXVALUE n| NOMAXVALUE ]
 [MINVALUE n | NOMINVALUE];
  [MINVALUE n | NOMINVALUE];
 修改序列可以:修改未来序列值的增量。
  修改序列可以:修改未来序列值的增量。
 设置或撤消最小值或最大值。
  设置或撤消最小值或最大值。
 改变缓冲序列的数目。
  改变缓冲序列的数目。
 指定序列号是否是有序。
  指定序列号是否是有序。
 注意:
  注意:
 1,第一次NEXTVAL返回的是初始值
  1,第一次NEXTVAL返回的是初始值
 2,可以alter除start至以外的所有sequence参数。如果想要改变start值,必须 drop sequence 再 re-create .
  2,可以alter除start至以外的所有sequence参数。如果想要改变start值,必须 drop sequence 再 re-create .
 3) 删除序列命令
  3) 删除序列命令
 DROP SEQUENCE [user.]sequence_name;
  DROP SEQUENCE [user.]sequence_name;
 用于从数据库中删除一序列。
  用于从数据库中删除一序列。
 4)牛刀小试
  4)牛刀小试
 4.1)创建一个序列号的语句:
  4.1)创建一个序列号的语句:
 -- Create sequence
  -- Create sequence
 create sequence NCME_QUESTION_SEQ
  create sequence NCME_QUESTION_SEQ
 minvalue 1
  minvalue 1
 maxvalue 999999999999
  maxvalue 999999999999
 start with 1
  start with 1
 increment by 1
  increment by 1
 nocache;
  nocache;
 //////////////////////////////
  //////////////////////////////
 4.2)SQL中取序列号的用法:
  4.2)SQL中取序列号的用法:
 SELECT NCME_QUESTION_SEQ.nextval FROM dual
  SELECT NCME_QUESTION_SEQ.nextval FROM dual
 SELECT NCME_QUESTION_SEQ.CURRVAL FROM dual
  SELECT NCME_QUESTION_SEQ.CURRVAL FROM dual
 SELECT NCME_QUESTION_SEQ.nextval FROM dual SELECT NCME_QUESTION_SEQ.CURRVAL FROM dual
  SELECT NCME_QUESTION_SEQ.nextval FROM dual SELECT NCME_QUESTION_SEQ.CURRVAL FROM dual
 注意:在使用序列的时候,有时需要有用户名,就像这样:
  注意:在使用序列的时候,有时需要有用户名,就像这样:
 insert into system.CONSERVATOR(CONSERVATORNAME,CONPASS,CONTRUENAME,CONSEX,CONID)values('JG','123456','000',0, system.CONID.nextval);
  insert into system.CONSERVATOR(CONSERVATORNAME,CONPASS,CONTRUENAME,CONSEX,CONID)values('JG','123456','000',0, system.CONID.nextval);参考资料链接:
关于DBMS_SQL包,动态SQL语句的问题
oracle 隐式游标,显示游标,游标循环,动态SELECT语句和动态游标,异常处理,自定义异常
oracle 创建,删除存储过程,参数传递,创建,删除存储函数,存储过程和函数的查看,包,系统包
几种使用动态SQL做游标的总结
关于动态SQL的使用
oracle创建存储过程
oracle创建函数,存储过程,视图以及for循环语法
oracle自定义函数