2010-05-21 22 views
26

Estoy tratando de pasar una matriz de datos (varchar) en un procedimiento de Oracle. El procedimiento de Oracle sería llamado ya sea desde SQL * Plus o de otro procedimiento PL/SQL, así:Pasar una matriz de datos como un parámetro de entrada a un procedimiento de Oracle

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

pr_perform_task leerá cada uno de los parámetros de entrada y llevar a cabo las tareas.

No estoy seguro de cómo puedo lograr esto. Lo primero que pensé fue utilizar un parámetro de entrada de tipo varray pero yo estoy Error: PLS-00201: identifier 'VARRAY' must be declared de error, cuando el definiton procedimiento es el siguiente:

CREATE OR REPLACE PROCEDURE PR_DELETE_RECORD_VARRAY(P_ID VARRAY) IS

En resumen, ¿cómo puedo pasar los datos como una matriz, dejar que el SP recorra cada uno de los parámetros y realice la tarea?

Estoy usando Oracle 10gR2 como mi base de datos.

Respuesta

39

Ésta es una manera de hacerlo:

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 

para ampliar mi comentario a la respuesta de @ dcp, aquí es cómo se puede implementar la solución propuesta allí si desea utilizar una matriz asociativa:

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> 

Este oficios creación de un independiente de Oracle TIPO (que no puede ser un array asociativo) con requiere la definición de un paquete que todos puedan ver para que el TIPO que define allí pueda ser utilizado por todos.

+0

Nice responder. Me preguntaba si es posible hacer lo que hace su primer método, pero para la situación donde el número de elementos en 't_in' es dinámico (es decir, es diferente para cada llamada a' testing'). Parece que uno necesita al menos codificar un límite superior para 'MyType'? ¿Puede esa restricción ser levantada de alguna manera? – ggkmath

+1

@ggkmath, no importa qué tan grande sea la matriz, pero debe declarar el límite superior de VARRAY cuando crea o altera el TIPO. – DCookie

+0

¿Existe una solución alternativa que pueda acomodar dicho tamaño dinámico, quizás sin VARRAY? Si no está relacionado, puedo comenzar un nuevo hilo. – ggkmath

6

Si los tipos de los parámetros son todos iguales (varchar2 por ejemplo), puede tener un paquete como éste, que hará lo siguiente:

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; 

Entonces, por llamarlo de que había necesidad de configurar la matriz y pasarlo:

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

No puede crear un tipo de Oracle de matriz asociativa. La única forma en que esto puede funcionar es definiendo el tipo en un paquete y haciendo referencia a él de esa manera. – DCookie

+0

@DCookie - Mi culpa, gracias por señalar el error. He corregido mi respuesta :). – dcp

+0

¿Es necesario crear un paquete? –

Cuestiones relacionadas