2010-05-21 50 views
26

我试图将(varchar)数据数组传递到Oracle过程。 Oracle过程会从SQL * Plus或从另一个PL/SQL程序,像这样既可以称为:将一组数据作为输入参数传递给Oracle过程

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

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

我不确定我是如何实现这一目标的。我首先想到的是使用varray类型的输入参数,但我得到Error: PLS-00201: identifier 'VARRAY' must be declared错误,当程序definiton看起来是这样的:

CREATE OR REPLACE PROCEDURE PR_DELETE_RECORD_VARRAY(P_ID VARRAY) IS

总之,我怎么能传递数据作为一个数组,让SP循环遍历每个参数并执行任务?

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

回答

39

这是做这件事:

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可以被所有人使用。

+0

不错回答。我想知道是否可以做你的第一个方法,但是对于't_in'中的元素数量是动态的(也就是说,每次调用'testing'都不同)?似乎需要至少硬编码“MyType”的上限?不知何故可以解除这个限制吗? – ggkmath 2012-08-26 01:02:49

+1

@ggkmath,数组的大小并不重要,但是当您创建或更改TYPE时,您必须声明VARRAY上限。 – DCookie 2012-08-26 01:23:04

+0

是否有替代解决方案可以适应这种动态大小,也许没有VARRAY?如果脱离主题,我可以开始一个新的线程。 – ggkmath 2012-08-26 03:34:33

6

如果类型的参数都是相同的(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; 
/
+0

您无法创建Oracle类型的关联数组。唯一可行的方法是在包中定义类型并以此方式引用它。 – DCookie 2010-05-21 21:38:50

+0

@DCookie - 我的错,谢谢你指出错误。我纠正了我的答案:)。 – dcp 2010-05-21 22:52:09

+0

它是否需要创建一个包? – 2015-11-04 15:54:14

相关问题