【问题标题】:Dynamically call PL/SQL procedure with output variables使用输出变量动态调用 PL/SQL 过程
【发布时间】:2013-04-23 20:44:44
【问题描述】:

我正在尝试使用动态 sql 来执行一个过程并检索输出参数:

v_sql := 'BEGIN ' || p_procname || '(''' || p_input1 || ''', ''' || p_input2 || ''', v_output1); END;';
DBMS_OUTPUT.PUT_LINE(v_sql);
EXECUTE IMMEDIATE v_sql;

我声明了 v_output1 变量,但收到以下错误消息:

PLS-00201: identifier 'V_ISSUE' must be declared 

如果我用来自v_sql 的 dbms_ouput 替换上述代码,则该过程有效,因此在过程方面没问题,问题在于我尝试动态调用它的方式。

我不知道我正在尝试做的事情是否会以这种方式工作。有没有办法通过动态 SQL 从这个过程调用中检索输出参数?

【问题讨论】:

    标签: oracle plsql oracle10g


    【解决方案1】:

    不要使用字符串连接将参数传递给动态 SQL。这完全被认为是一种不好的做法,不仅对 Oracle 而言。

    这很糟糕,但主要的失败点是在动态 SQL 字符串中使用局部变量的名称,因为它在引入该变量的代码块之外的任何地方都不可见。

    您的代码应如下所示:

    declare 
      v_sql varchar2(4000);
      p_procname varchar2(100);
      p_input1 number;
      p_input2 number;
      v_output1 number;   
    begin
    
      v_sql := 'begin ' || p_procname || '(:p_input1, :p_input2, :v_output); end;';
    
      execute immediate v_sql 
      using in p_input1, in p_input2, out v_output1;
    
    end;
    

    【讨论】:

    • p_procname 也是一个变量,你不能绑定它,所以你必须像保罗在他的回答中所做的那样连接它。
    【解决方案2】:

    找到我的答案here

    v_sql := 'BEGIN ' || p_procname || '(:a, :b, :c); END;';
    
    EXECUTE IMMEDIATE v_sql
    USING IN p_input1, IN p_input2, OUT v_output1;
    

    【讨论】:

    • 自己找到答案做得很好 *8-) 但是,在字符串连接上使用绑定变量的主要原因之一是防止 SQL 注入。由于您无法绑定过程名称,如果您确实必须将其作为传入变量,您需要以某种方式验证是否未尝试注入,也许通过检查该名称的 proc 确实存在于数据中字典,并将其用作该查询中的绑定变量。
    • @AlexPoole dbms_utility.name_resolve 应该可以处理这个
    猜你喜欢
    • 2021-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-02
    • 2015-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多