Гость
Форумы / Oracle [игнор отключен] [закрыт для гостей] / execute immediate / 13 сообщений из 13, страница 1 из 1
04.09.2019, 10:50
    #39857001
Kaktus_87
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
execute immediate
Добрый день, помогите плз собрать динамический блок execute immediate, в который я бы мог передавать название сиквенса из переменной.(т.е чтоб получилось что-то типо этого SELECT || seq || .nextval into m from dual;) Также записывать значения этого сиквенса в переменную.
Я знаю, что в динамическом sql можно собрать запрос с переменными, но как это делается ни как не пойму.

Также подскажите, если другой способ увеличить последовательность сиквенса число N ? - гугл не помог (

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
DECLARE
seq VARCHAR2(20) := 'BF_SEQ'; --название сиквенса
d NUMBER := 10000000; --На сколько увеличиваем сиквенс
n NUMBER; --текущее значение сиквенса
m NUMBER; --Измененное значение сиквенса

BEGIN
SELECT BF_SEQ.nextval into n from dual;
--execute immediate 'SELECT ' || seq || '.nextval' into n from dual; --хочется получить, что-то типо этого

execute immediate 'ALTER SEQUENCE BF_SEQ INCREMENT BY  '|| d ;

SELECT BF_SEQ.nextval into m  from dual;

execute immediate 'ALTER SEQUENCE BF_SEQ INCREMENT BY  1';

DBMS_OUTPUT.Put_Line( 'n= '|| n );
DBMS_OUTPUT.Put_Line( 'm= '|| m );
DBMS_OUTPUT.Put_Line( 'd= '|| d ); 
end;
...
Рейтинг: 0 / 0
04.09.2019, 10:59
    #39857005
CrazyCat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
execute immediate
Kaktus_87,

Гуглом принципиально не пользуемся?
https://docs.oracle.com/cd/B12037_01/appdev.101/b10807/13_elems017.htm

см. examples
...
Рейтинг: 0 / 0
04.09.2019, 11:13
    #39857017
oragraf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
execute immediate
Kaktus_87,

держи на подумать:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
  /* Процедура осуществляет перекидку сиквенса согласно значению поля таблицы.
     Если колонка не передана, то процедура пытается найти колонку через
     констрейнты. Если ключ - составной или ключ нечисловой или таблицы нет - исключение
  */
  procedure alter_sequence_nextval (p_table_name    varchar2
                                  , p_column_name   varchar2 := null
                                  , p_sequence_name varchar2 := null
                                   )
    as
    number_fmt               constant varchar2 (100) := 'fm99999999999999999999999';
    l_seq_currval                     number;
    l_seq_incrementby                 number;
    l_seq_nextval                     number;
    l_seq_cache                       number;
    l_tab_currval                     number;
    l_tab_nextval                     number;
    l_dml                             varchar2 (1000 char);
    l_column_name                     varchar2 (30 char);
    l_table_name                      varchar2 (30 char);
    l_sequence_name                   varchar2 (30 char);
  begin
    l_table_name := UPPER (DBMS_ASSERT.sql_object_name (p_table_name));
    l_sequence_name := UPPER (DBMS_ASSERT.sql_object_name (p_sequence_name));
    l_column_name := TRIM (p_column_name);

    if l_column_name is not null
    then
       l_column_name := DBMS_ASSERT.simple_sql_name (p_column_name);
    else
       begin
          select cc.column_name
            into l_column_name
            from user_constraints c
                 inner join user_cons_columns cc on cc.constraint_name = c.constraint_name and cc.owner = c.owner
                 inner join user_tab_columns tc on tc.table_name = cc.table_name and tc.column_name = cc.column_name
           where c.constraint_type in ('P', 'U') and tc.data_type in ('NUMBER', 'INTEGER') and UPPER (tc.table_name) = l_table_name;
       exception
          when NO_DATA_FOUND
          then
             raise DBMS_ASSERT.invalid_object_name;
          when TOO_MANY_ROWS
          then
             utl_ddl.error ('Таблица ' || l_table_name || ' имеет составной ключ! Укажите требуемую колонку');
             raise exc#invalid_identifier;
       end;
    end if;

    l_dml := 'select s.increment_by, s.cache_size from user_sequences s where sequence_name = upper(trim(:1))';

    execute immediate l_dml into l_seq_incrementby, l_seq_cache using l_sequence_name;

    l_dml := 'begin select max(' || l_column_name || ') into :1 from ' || l_table_name || '; :2 := ' || l_sequence_name || '.nextval; end;';

    execute immediate l_dml using out l_tab_currval, out l_seq_currval;

    if l_tab_currval > l_seq_currval -- В случае, если строго больше, тогда меняем инкремент
    then
       l_dml := 'alter sequence ' || l_sequence_name || ' increment by ' || TO_CHAR (l_tab_currval - l_seq_currval, number_fmt) || ' nocache';
       execute immediate l_dml;

       l_dml := 'begin :2 := ' || l_sequence_name || '.nextval; end;';
       execute immediate l_dml using out l_tab_nextval;

       execute immediate 'alter sequence ' || l_sequence_name || 
                         ' increment by ' || TO_CHAR (l_seq_incrementby, number_fmt) || 
                         case when l_seq_cache = 0 then ' nocache' 
                              else ' cache ' || to_char(l_seq_cache, number_fmt)
                         end;
    elsif l_tab_currval = l_seq_currval
    then -- В редких случаях, когда равны, просто еще раз дернем сиквенс, чтобы не делать alter

       l_dml := 'begin :2 := ' || l_sequence_name || '.nextval; end;';
       execute immediate l_dml using out l_tab_nextval;    

    end if;

    exception
       when DBMS_ASSERT.invalid_object_name
       then
          utl_ddl.error ('Таблицы ' || p_table_name || ' с числовым полем для сиквенса не существует');
          raise exc#invalid_identifier;
       when DBMS_ASSERT.invalid_sql_name
       then
          utl_ddl.error ('Колонка ' || p_table_name || '.' || p_column_name || ' не существует');
          raise exc#invalid_identifier;
    end;
...
Рейтинг: 0 / 0
04.09.2019, 11:17
    #39857022
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
execute immediate
...
Рейтинг: 0 / 0
04.09.2019, 14:59
    #39857236
Kaktus_87
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
execute immediate
oragraf,
Спасибо большое.
В принципе мне нужна было 2 таких строчки:
Код: plsql
1.
2.
3.
4.
...
l_plsql := 'begin select ' || seq_name || '.nextval into :1 from dual; end;';
execute immediate l_plsql using out seq_currval;
...
...
Рейтинг: 0 / 0
04.09.2019, 16:03
    #39857302
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
execute immediate
Kaktus_87
Код: plsql
1.
2.
l_plsql := 'begin select ' || seq_name || '.nextval into :1 from dual; end;';
execute immediate l_plsql using out seq_currval;

Ужас.
...
Рейтинг: 0 / 0
05.09.2019, 09:12
    #39857712
Kaktus_87
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
execute immediate
Elic,
Что не так?
...
Рейтинг: 0 / 0
05.09.2019, 09:20
    #39857716
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
execute immediate
Kaktus_87Что не так?Ты не понял, как PL/SQL-ьно обращаться к последовательности. А затем усугубил динамический запрос бессмысленным оборачиванием в PL/SQL.
...
Рейтинг: 0 / 0
05.09.2019, 10:06
    #39857748
Kaktus_87
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
execute immediate
Elic,
Как будет правильно? Так?

Код: plsql
1.
2.
3.
4.
...
l_plsql  := 'begin :2 := ' || seq_name || '.nextval;end;';
execute immediate l_plsql using out n_seq;
...
...
Рейтинг: 0 / 0
05.09.2019, 10:18
    #39857759
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
execute immediate
Kaktus_87Как будет правильно? Так?Какая тебе разница? Немотивированное динамическое обращение к последовательности без знания основ - это говнокод по определению. Степень говнокодистости непринципиальна.
...
Рейтинг: 0 / 0
05.09.2019, 10:27
    #39857767
Kaktus_87
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
execute immediate
авторКакая тебе разница?
Хочется понять как правильно, я только учусь. С oracle познакомился полгода назад только.
...
Рейтинг: 0 / 0
05.09.2019, 10:42
    #39857775
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
execute immediate
Kaktus_87,

в древних версиях не прокатит

.....
stax
...
Рейтинг: 0 / 0
05.09.2019, 10:49
    #39857777
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
execute immediate
Kaktus_87авторКакая тебе разница?
Хочется понять как правильно, я только учусь. С oracle познакомился полгода назад только.
имхо, от версий зависит

для древних, я кодировал примерно так
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
SQL> ed
Wrote file afiedt.buf

  1  declare
  2   v varchar2(100);
  3   s number;
  4  begin
  5   v:='s';
  6   execute immediate 'select '||v||'.nextval from dual' into s;
  7   dbms_output.put_line(s);
  8* end;
SQL> /
224

PL/SQL procedure successfully completed.



....
stax
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / execute immediate / 13 сообщений из 13, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]