【问题标题】:Passing an array of data as an input parameter to an Oracle procedure将数据数组作为输入参数传递给 Oracle 过程
【发布时间】:2011-02-22 13:20:40
【问题描述】:

我正在尝试将一组 (varchar) 数据传递到 Oracle 过程中。 Oracle 过程可以从 SQL*Plus 或另一个 PL/SQL 过程调用,如下所示:

BEGIN
 pr_perform_task('1','2','3','4');
END;

pr_perform_task 将读取每个输入参数并执行任务。

我不确定如何实现这一目标。我的第一个想法是使用 varray 类型的输入参数,但是当过程定义如下所示时,我收到了 Error: PLS-00201: identifier 'VARRAY' must be declared 错误:

CREATE OR REPLACE PROCEDURE PR_DELETE_RECORD_VARRAY(P_ID VARRAY) IS

总而言之,如何将数据作为数组传递,让 SP 循环遍历每个参数并执行任务?

我使用 Oracle 10gR2 作为我的数据库。

【问题讨论】:

    标签: oracle stored-procedures plsql


    【解决方案1】:

    如果参数的类型都是相同的(例如varchar2),你可以有一个这样的包,它将执行以下操作:

    CREATE OR REPLACE PACKAGE testuser.test_pkg IS
    
       TYPE assoc_array_varchar2_t IS TABLE OF VARCHAR2(4000) INDEX BY BINARY_INTEGER;
    
       PROCEDURE your_proc(p_parm IN assoc_array_varchar2_t);
    
    END test_pkg;
    
    CREATE OR REPLACE PACKAGE BODY testuser.test_pkg IS
    
       PROCEDURE your_proc(p_parm IN assoc_array_varchar2_t) AS
       BEGIN
          FOR i IN p_parm.first .. p_parm.last
          LOOP
             dbms_output.put_line(p_parm(i));
          END LOOP;
    
       END;
    
    END test_pkg;
    

    然后,要调用它,您需要设置数组并传递它:

    DECLARE
      l_array testuser.test_pkg.assoc_array_varchar2_t;
    BEGIN
      l_array(0) := 'hello';
      l_array(1) := 'there';  
    
      testuser.test_pkg.your_proc(l_array);
    END;
    /
    

    【讨论】:

    • 您无法创建关联数组的 Oracle 类型。唯一可行的方法是在包中定义类型并以这种方式引用它。
    • @DCookie - 我的错,感谢您指出错误。我已经更正了我的答案:)。
    • 是否需要创建一个包?
    • 我认为你问错了问题。除了极少数情况,您应该始终使用包,参考这里:asktom.oracle.com/pls/asktom/…
    【解决方案2】:

    这是一种方法:

    SQL> set serveroutput on
    SQL> CREATE OR REPLACE TYPE MyType AS VARRAY(200) OF VARCHAR2(50);
      2  /
    
    Type created
    
    SQL> CREATE OR REPLACE PROCEDURE testing (t_in MyType) IS
      2  BEGIN
      3    FOR i IN 1..t_in.count LOOP
      4      dbms_output.put_line(t_in(i));
      5    END LOOP;
      6  END;
      7  /
    
    Procedure created
    
    SQL> DECLARE
      2    v_t MyType;
      3  BEGIN
      4    v_t := MyType();
      5    v_t.EXTEND(10);
      6    v_t(1) := 'this is a test';
      7    v_t(2) := 'A second test line';
      8    testing(v_t);
      9  END;
     10  /
    
    this is a test
    A second test line
    

    为了扩展我对@dcp 的回答的评论,如果您想使用关联数组,您可以通过以下方式实施那里提出的解决方案:

    SQL> CREATE OR REPLACE PACKAGE p IS
      2    TYPE p_type IS TABLE OF VARCHAR2(50) INDEX BY BINARY_INTEGER;
      3  
      4    PROCEDURE pp (inp p_type);
      5  END p;
      6  /
    
    Package created
    SQL> CREATE OR REPLACE PACKAGE BODY p IS
      2    PROCEDURE pp (inp p_type) IS
      3    BEGIN
      4      FOR i IN 1..inp.count LOOP
      5        dbms_output.put_line(inp(i));
      6      END LOOP;
      7    END pp;
      8  END p;
      9  /
    
    Package body created
    SQL> DECLARE
      2    v_t p.p_type;
      3  BEGIN
      4    v_t(1) := 'this is a test of p';
      5    v_t(2) := 'A second test line for p';
      6    p.pp(v_t);
      7  END;
      8  /
    
    this is a test of p
    A second test line for p
    
    PL/SQL procedure successfully completed
    
    SQL> 
    

    这相当于创建一个独立的 Oracle TYPE(不能是关联数组),需要定义一个所有人都可以看到的包,以便所有人都可以使用它在那里定义的 TYPE。

    【讨论】:

    • 不错的答案。我想知道是否可以执行您的第一种方法,但是对于t_in 中的元素数量是动态的(即,每次调用testing 时它是不同的)的情况?似乎至少需要硬编码MyType 的上限?能以某种方式解除这个限制吗?
    • @ggkmath,不管数组有多大,但是你必须在创建或修改TYPE的时候声明VARRAY的上限。
    • 是否有替代解决方案可以适应这种动态大小,也许没有 VARRAY?如果题外话,我可以开个新帖。
    • 使用答案的后半部分 - 将类型设为 PL/SQL 关联数组并在包规范中定义。
    • 对我来说,我必须使用以下 v_t p.p_type = p.p_type(); 初始化表类型稍后调用 v_t.extend(10) 为 10 个元素创建空间。不知道为什么它与你正在做的和我所拥有的不同。 Btween 我创建了一个我们创建的类型的 table_type
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-09
    • 2011-07-09
    • 2012-11-23
    • 2014-12-26
    • 1970-01-01
    相关资源
    最近更新 更多