2017-02-08 38 views
-1

Я пытаюсь передать dbms_sql.number_table из одной процедуры в другую и затем использовать ее внутри динамического блока plsql. Но приведенный ниже код порождает ошибку как:Использование коллекции внутри динамического sql

Ошибка (6,17): PLS-00306: неправильное количество или типы аргументов при вызове '||'

create or replace 
procedure proc1(v_in_table_name varchar2, 
       v_in_column_name varchar2, 
       v_in dbms_sql.number_table) 
as 
plsql_block varchar2(4000); 
begin 
    plsql_block:='declare 

       begin 
         FORALL INDX IN 1 ..'||v_in.count||' SAVE EXCEPTIONS 
         UPDATE '||v_in_table_name||' 
         Set '||v_in_column_name||'=123 WHERE col2='||v_in||'(INDX)||; 
       end'; 
    execute immediate plsql_block; 
end proc1; 

ответ

0

Вы должны сделать два изменения: Во-первых (и его случай ошибки) его, когда вы concatinate строку коллекции. Если вы хотите отправить коллекцию в блок pl/sql, вы используете параметр param. И второе, вы должны добавить ; в конце динамического PL \ SQL:

create or replace 
procedure proc1(v_in dbms_sql.number_table) 
as 
plsql_block varchar2(4000); 
begin 
    plsql_block:='declare 
        l_collect dbms_sql.number_table := :number_table ; 
       begin 
         FORALL INDX IN 1 ..'||v_in.count||' SAVE EXCEPTIONS 
         UPDATE table_name 
         Set col1=123 WHERE col2=l_collect(INDX); 
       end;'; 
    execute immediate plsql_block using v_in; 
end proc1; 

Но после того, как все изменения, которые я хотел бы спросить: Вы действительно должны использовать динамический PL \ SQL?

+0

Это не будет работать. вы пробовали это в конце. – XING

+0

Да, я попробую. И это работает –

+0

Не знаете, где вы пробовали coz У меня есть оракул 11gR2, и он дает мне эту ошибку 'PLS-00457: выражения должны быть типа SQL'. Я бы сказал, попробуйте еще раз и опубликуем рабочую версию – XING

0

Нет необходимости использовать динамический блок. Также я не думаю, что он может работать. Вы можете использовать этот способ;

create or replace 
procedure proc1(v_in dbms_sql.number_table) 
as 
plsql_block varchar2(4000); 

l_collect dbms_sql.number_table; 

begin 

l_collect := v_in; 

FORALL INDX IN 1 ..l_collect.count SAVE EXCEPTIONS 
     UPDATE table_name 
    Set col1=123 
    WHERE col2=l_collect(INDX); 

commit; 
end proc1; 

Исполнение:

SQL> DECLARE 
     var DBMS_SQL.number_table; 
     BEGIN 
     var (1) := 1; 
     var (2) := 2; 
     var (3) := 3; 
     proc1 (var); 
     END;  
    /

PL/SQL procedure successfully completed. 

EDIT: В соответствии с Вашим редактировать код становится как:

create or replace procedure proc1 (v_in_table_name  varchar2, 
            v_in_column_name varchar2, 
            v_in    dbms_sql.number_table) 
as 
    plsql_block varchar2 (4000); 
begin 
    plsql_block := q'[ FORALL INDX IN 1 ..v_in.count SAVE EXCEPTIONS 
          UPDATE :table_name 
          Set :col1=123 
          WHERE col2=v_in(INDX)]'; 

    execute immediate plsql_block using v_in_table_name, v_in_column_name; 

    commit; 
end proc1; 
+0

Я делаю некоторые другие обработки внутри динамического блока plsql, поэтому мне нужно, чтобы все внутри динамического блока. – PTK

+0

Вы просто зацикливаете данные внутри коллекции. Я тоже делаю то же самое. Я просто копирую данные в переменную и запускаю ее. Необходимость динамического блока здесь бесполезна – XING

+0

Мое требование таково, что мне нужно использовать динамический блок – PTK