【问题标题】:Using collection inside dynamic sql在动态 sql 中使用集合
【发布时间】:2017-02-08 08:13:18
【问题描述】:

我正在尝试将 dbms_sql.number_table 从一个过程传递到另一个过程,然后在动态 plsql 块中使用它。但是下面的代码会抛出错误:

错误(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;

【问题讨论】:

    标签: oracle plsql numbers dynamic-sql


    【解决方案1】:

    您应该进行两项更改: 首先(及其错误情况)是当您将字符串与集合连接时。 如果要将集合发送到 pl/sql 块中,则应使用参数。 其次,您应该在动态 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 吗?

    【讨论】:

    • 不确定你在哪里试过因为我有 oracle 11gR2,它给了我这个错误PLS-00457: expressions have to be of SQL types。我会说再试一次并发布工作版本
    • 编译时出现此错误 Error(13,41): PLS-00457: 表达式必须是 SQL 类型
    【解决方案2】:

    不需要使用动态块。我也不认为它也可以工作。你可以这样用;

    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.
    

    编辑:根据您的编辑,代码如下:

     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;
    

    【讨论】:

    • 我正在动态 plsql 块中进行其他处理,所以我需要在动态块中进行所有处理。
    • 您只是在循环集合内的数据。我也在做同样的事情。我只是将数据处理为一个变量并运行它。动态块的需要在这里没用
    • 我的要求是需要使用动态块
    • 您想使用动态 sql 实现什么。因为无论您想实现什么,都可以使用上述方法完成。
    • 更新语句中的表名是动态的,因此是动态块
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多