Получить следующее значение из oracle sequence, которое создается динамически и в форме varchar2 или строки

Я динамически создаю последовательность на основе нескольких комбинаций. Как мне получить 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 имеют одинаковое значение, скажем, 12345 и 94 для значения SRNO от 1 до 1000. Затем другой набор LOC_CD и GR_NO скажет 67890 и 95 с SRNO 1 t0 1000 с unqiue CONS_NO и так далее.

Мне нужно использовать эти наборы LOC_CD и GR_NO в многопоточности с использованием Java. Например, набор LOC_CD и GR_NO со значением 12345 и 94 (имеющий 1000 записей в таблице A) будет обрабатываться в 10 потоках (количество записей на поток равно 100). Каждый поток вызовет процедуру INSERTPROC. Перед вызовом многопоточности для набора LOC_CD и GR_NO я динамически создаю sequecne, скажем, SE1234594, а для другого набора SE6789095 и так далее ....

для set1 LOC_CD и GR_NO вызовы из многопоточности 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.

для set2 LOC_CD и GR_NO 67890 95 вызовы из многопоточности 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 и представляет собой комбинацию LOC_CD и GR_NO в процедуре INSERTPROC

К сожалению, я не могу использовать rownum и autoincrement в таблице tab3, поскольку rownum генерирует тот же sr_no, если процесс выполняется в параллельных потоках, autoincrment не будет начинаться с 1 для следующего набора многопоточных вызовов для LOC_CD и GR_NO.)

Ваша последовательность еще не создана, поэтому блок PL / SQL не сможет скомпилировать, поскольку он не найдет последовательности с таким именем. Это сообщение об ошибке времени компиляции от Oracle, которое проверяет, действительно ли присутствуют все зависимые объекты, на которые имеется ссылка.

Kaushik Nayak 31.10.2018 14:37

@KaushikNayak, даже если я использую уже созданную последовательность, я получаю ту же ошибку. loc_cd: = '12345'; gr_cd: = '94'; seq: = 'SE' || loc_cd || gr_cd; dbms_output.put_line (seq.nextval); Но если я использую имя напрямую SE1234594.nextvalu, оно работает ...

Manish Suriya 01.11.2018 06:42

Да все верно. Вы не можете напрямую ссылаться на имена объектов (таблица, последовательность и т. д.) И имена столбцов через переменные, execute immediate предназначен для такой операции.

Kaushik Nayak 01.11.2018 06:52

На самом деле у меня есть процедура (insertproc), которая вызывается из Java в многопоточности. этот процесс выполняет вставку примерно так, как показано ниже, здесь loc_cd и gr_cd - это входы для процесса, используя эти входы, мне нужно получить следующее значение последовательности. к сожалению, я не могу использовать rownum и autoincrement, поскольку rownum генерирует тот же sr_no, если proc выполняется в параллельных потоках, autoincrment не будет начинаться с 1 для следующего набора вызовов нескольких потоков.

Manish Suriya 01.11.2018 07:25

процедура insertproc (loc_cd IN VARCHAR2, gr_cd IN VARCHAR2, countstrt в числе, подсчитывается в количестве) как --declration part begin insert into tab3 (sr_no, col1, col2) (выберите 'SE' || loc_cd || gr_cd.nextval, col1 , col2 (выберите col1, col2 из tab1 a, tab2 b, где b.counnum между countstrt и countend / * еще одно условие * /)) end;

Manish Suriya 01.11.2018 07:27

Не добавляйте детали в виде комментариев, это плохо читается. Отредактируйте свой вопрос и добавьте соответствующие сведения, подробно объясняя проблему, с которой вы столкнулись. См. Кнопку редактирования под тегами.

Kaushik Nayak 01.11.2018 07:47

@KaushikNayak, пожалуйста, посмотрите правку.

Manish Suriya 01.11.2018 08:26

Почему бы не выбрать сам a.SRNO в операторе вставки для заполнения tab3.sr_no, разве эти числа не будут такими же?

Kaushik Nayak 01.11.2018 12:48

a.SRNO будет одинаковым для каждого номера потока, поэтому я получу повторяющиеся значения tab3.sr_no. Я также хочу иметь уникальный SR_NO для tab3.

Manish Suriya 01.11.2018 13:14

Возможно, я еще не полностью понял ваше приложение, но мне все еще не ясно, как вы определяете начальные и конечные значения динамической последовательности, которую вы создаете для каждого набора

Kaushik Nayak 01.11.2018 13:29

Из того, что я могу сделать вывод, вам нужна только одна последовательность, назовем ее исключительно tab3_seq для увеличения значений только в tab3, а в вашей процедуре просто используйте tab3_seq.nextval в операторе вставки. Oracle автоматически решит остальные проблемы параллелизма для ваших потоков.

Kaushik Nayak 01.11.2018 13:41

@KaushikNayak, пожалуйста, проверьте мой ответ. Не уверен, что это лучший способ достичь. И да, мне пришлось использовать немедленное выполнение. Другого выхода у меня не было :)

Manish Suriya 01.11.2018 14:09

Метод, который вы придумали, вовсе не является приемлемым решением. Цикл по записям неоптимален и вызовет проблемы с производительностью сейчас или позже, особенно если у вас многопоточный подход. Похоже, что это всего лишь обходной путь для решения возникшей проблемы, а не поиск надежного решения исходной проблемы.

Kaushik Nayak 01.11.2018 14:21
0
13
516
2

Ответы 2

Я могу достичь того, чего хочу, создав процесс, который приносит мне 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;

Хотя этот процесс ухудшает общую производительность. Но все равно нормально. Любые другие предложения по оригинальному решению приветствуются.

Я предлагаю использовать одну последовательность 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;
/

Я пробовал ваше решение, но оно дает 111111ORA-00955: name уже используется существующим объектом, когда более одного набора экземпляров потоков выполняется параллельно для двух разных наборов loc_cd и gr_cd paralley.

Manish Suriya 02.11.2018 13:41

@Manish Suriya: Вы должны создать последовательность только один раз, и это не должно зависеть от процедуры или потоков. Кажется, вы пытаетесь создать одну и ту же последовательность 2 или более раз

Kaushik Nayak 02.11.2018 14:21

Если я не буду создавать новый seq для нового набора loc_cd и gr_no, sr_no не будет strt от 1. и я хочу srno от 1 для каждого набора loc_cd и gr_no

Manish Suriya 02.11.2018 14:28

@Manish Suriya: Но в одном из своих комментариев вы сказали: «Я также хочу иметь уникальный SR_NO для tab3». Вы имели в виду, что хотите, чтобы он был уникальным в tab3 для всего набора, а не для всей таблицы?

Kaushik Nayak 02.11.2018 14:42

@ManishSuriya: Хорошо, спасибо, что разъяснили. Это означает, что вы можете использовать ROWNUM + countstrt как sr_no right (а не просто ROWNUM, как вы уже пробовали)?

Kaushik Nayak 05.11.2018 11:36

Другие вопросы по теме