从Oracle Sequence获取nextvalue,该值是动态生成的,格式为varchar2或字符串

时间:2018-10-31 12:10:45

标签: oracle plsql oracle11g sequence

我正在基于少量组合动态创建序列。我如何从这个动态生成的序列中得到nextVal

declare

loc_cd varchar2(10);
gr_cd varchar2(10);
seqval number;
seq varchar2(2000);
st varchar2(2000);
v_select varchar2(2000);
begin

loc_cd :='12345';
gr_cd :='99';

seq := 'SE'||loc_cd||gr_cd; 
dbms_output.put_line(seq);

 st := 'create sequence ' ||seq|| ' minvalue 1 maxvalue 99999999999 start with 1 increment by 1 cache 20' ;
dbms_output.put_line(st);
execute immediate st;
dbms_output.put_line('seq created'); 


v_select := 'select '||seq||'.nextval from dual';
execute immediate v_select into seqval; 
dbms_output.put_line(seqval); --This is ok


  dbms_output.put_line( seq.nextval);  -- This is not. how to achieve this ?
end;

我在使用seq.nextval时遇到问题** Invalid refrence to variable SEQ .**

我不想在下面使用

v_select := 'select '||seq||'.nextval from dual';
        execute immediate v_select into seqval;

编辑以进一步阐明我想要实现的目标

我有一个tableA,其中包含CONS_NO,LOC_CD,GR_NO和SRNO列,具有数千条记录。 CONS_NO具有唯一的记录,LOC_CD和GR_NO具有相同的值,例如SRNO值从1到1000表示为12345和94。然后另一组LOC_CD和GR_NO的SRNO为1 t0 1000则表示67890和95,具有不连续的CONS_NO,等等。

我需要使用Java在多线程中处理这些LOC_CD和GR_NO集。例如,一组LOC_CD&GR_NO的值为12345和94(在tableA中具有1000条记录)将在10个线程中处理(每个线程的记录数为100)。每个线程将调用一个过程INSERTPROC。在为一组LOC_CD和GR_NO调用多线程之前,我正在动态创建sequecne说SE1234594,并为另一组SE6789095等等。...

对于LOC_CD和GR_NO的set1,来自Java多线程的调用就像..

seq SE1234594 created 
procedure  INSERTPROC('12345', '94', 1,  100)
procedure  INSERTPROC('12345', '94', 101,  200) 
.....
procedure  INSERTPROC('12345', '94', 901,  1000)
seq SE1234594 dropped.

对于LOC_CD和GR_NO的set2 67890来自Java多线程的调用就像..

seq SE6789095 created 

procedure  INSERTPROC('67890', '95', 1,  100)
procedure  INSERTPROC('67890', '95', 101,  200) 
.....
procedure  INSERTPROC('67890', '95', 901,  1000)
seq SE6789095 dropped 

INSERTPROC的结构如下所示

procedure INSERTPROC(loc_cd  IN VARCHAR2, gr_cd IN VARCHAR2, countstrt number, countend number) as 
--declration part
begin

insert into tab3 (sr_no, col1, col2)
  (select 'SE'||loc_cd||gr_cd.nextval, --how to use seq here ?
          col1,
          col2 from (select col1, col2 from tableA a, tab1 b   where  a.SRNO  between countstrt and countend /*some more condition */           
                )  
   )
end ;

我的问题:如何在Java INSERTPROC程序中使用通过Java代码动态生成且由LOC_CD和GR_NO组合而成的序列

不幸的是,我无法在表tab3上使用rownum和autoincrement,因为如果proc在并行线程中运行,则rownum会生成相同的sr_no,对于下一组LOC_CD和GR_NO的多线程调用,autoincrment不会以1开头。)

2 个答案:

答案 0 :(得分:0)

我能够通过创建一个过程来实现我想要的目标,该过程使我nextval从动态创建的序列中移出。

CREATE OR REPLACE PROCEDURE callSeq(
 seqname IN varchar2,
 seqval OUT number
 )
IS

v_select varchar2(1000);

BEGIN

   v_select := 'select '||seqname||'.nextval from dual';
   execute immediate v_select into seqval;
   /*  dbms_output.put_line(seqval);*/


END;

并在INSERTPROC中将此进程用作

CREATE OR REPLACE PROCEDURE INSERTPROC(LOC_CD  IN VARCHAR2,
                                             GR_CD IN VARCHAR2,                                                 
                                            countstrt in number, countend in number

                                             ) is

declare
 seqval number;
BEGIN 
   FOR c IN  (select LOC_CD, GR_CD  from tableA a, tab1 b   where  a.SRNO  between countstrt and countend /*some more condition */           
                )  
     LOOP
     callSeq('SE'||c.LOC_CD||c.GR_CD,seqval) ;
 insert into tab3 (col1, col2, sr_no) values(c.LC_CD, c.GR_CD ,seqval) ;          
   END LOOP;  
END;

尽管此过程会降低整体性能。但是还是可以的。欢迎对原始解决方案提出任何其他建议。

答案 1 :(得分:0)

我的建议是专门为tab3_seq使用单个序列tab3,并让Oracle使用相同的序列来处理并发线程。

CREATE OR REPLACE PROCEDURE insertproc (
     loc_cd      IN VARCHAR2,
     gr_cd       IN VARCHAR2,
     countstrt   IN NUMBER,
     countend    IN NUMBER
) IS

BEGIN
     INSERT INTO tab3 (
          sr_no,
          col1,
          col2
     )
          SELECT tab3_seq.NEXTVAL, -- This will not overlap while being used by multiple sessions  
                 col1,
                 col2
          FROM tablea a
          JOIN             --Use proper Join syntax rather than obsolete a,b syntax 
           tab1 b ON ( a.id = b.id ) --your Join condition 
          WHERE a.srno BETWEEN countstrt AND countend /*some more condition */
END;
/