2009-11-11 12 views
7

ODP.Net expone la capacidad de pasar matrices asociativas como parámetros en un procedimiento almacenado de Oracle desde C#. Es una buena característica a menos que intente utilizar los datos contenidos en esa matriz asociativa en una consulta sql.Cómo usar una matriz asociativa de Oracle en una consulta SQL

La razón de esto es que requiere un cambio de contexto: las sentencias de SQL requieren tipos de SQL y una matriz asociativa pasada a PL/SQL, como esto realmente se define como un tipo de PL/SQL. Creo que cualquier tipo definido dentro de un paquete/procedimiento/función PL/SQL son tipos PL/SQL, mientras que un tipo creado fuera de estos objetos es un tipo SQL (si puede proporcionar más claridad sobre eso, por favor, pero no es el objetivo de este pregunta).

Entonces, la pregunta es, ¿cuáles son los métodos que usaría para convertir la matriz asociativa parámetro PL/SQL en algo que en el procedimiento se puede utilizar en una instrucción SQL como esto:

OPEN refCursor FOR 
SELECT T.* 
FROM SOME_TABLE T, 
     (SELECT COLUMN_VALUE V 
     FROM TABLE(associativeArray) 
     ) T2 
WHERE T.NAME = T2.V; 

Para a los fines de este ejemplo, el "array asociativo" es una tabla simple de varchar2 (200) indexada por PLS_INTEGER. En C#, el parámetro Array asociativo se rellena con una cadena [].

Siéntase libre de discutir otras formas de hacer esto además de usar una matriz asociativa, pero sepa con anticipación que esas soluciones no serán aceptadas. Aún así, estoy interesado en ver otras opciones.

+0

Ver aquí para una solución similar + problema similar: http://stackoverflow.com/questions/1625649/oracle- parameters-with-in-statement/1655743 # 1655743 – tuinstoel

Respuesta

11

me gustaría crear un tipo de base de datos de la siguiente manera:

create type v2t as table of varchar2(30); 
/

Y luego, en el procedimiento:

FOR i IN 1..associativeArray.COUNT LOOP 
    databaseArray.extend(1); 
    databaseArray(i) := associativeArray(i); 
END LOOP; 

OPEN refCursor FOR 
SELECT T.* 
FROM SOME_TABLE T, 
     (SELECT COLUMN_VALUE V 
     FROM TABLE(databaseArray) 
     ) T2 
WHERE T.NAME = T2.V; 

+0

Sí, eso funciona. – ScottCher

+4

Es asombroso cuántos ejemplos hay de utilizar matrices asociativas en bucles para ejecutar inserciones y cosas así, pero ninguna que discuta o proporcione ejemplos para eludir el problema del cambio de contexto. Espero que esto sea útil también para otros. – ScottCher

+0

Esto no está creando una matriz asociativa; está creando una colección. También tenga en cuenta: 'asscoiativeArray.FIRST' puede no ser' 1' y 'asociativeArray.COUNT' y' asociativeArray.LAST' pueden no ser iguales (especialmente si la matriz asociativa es escasa). – MT0

1

(donde databaseArray se declara de tipo V2T). No puede usar matrices asociativas en el ámbito de SQL, solo se pueden usar en el alcance de PL/SQL.

Un método es asignar la matriz asociativa a una colección (que se puede usar en el ámbito SQL si el tipo de colección se ha definido en el ámbito SQL y no en el ámbito PL/SQL).

SQL:

CREATE TYPE VARCHAR2_200_Array_Type AS TABLE OF VARCHAR2(200); 
/

PL/SQL

DECLARE 
    TYPE associativeArrayType IS TABLE OF VARCHAR2(200) INDEX BY PLS_INTEGER; 
    i    PLS_INTEGER; 
    associativeArray associativeArrayType; 
    array   VARCHAR2_200_Array_Type; 
    cur    SYS_REFCURSOR; 
BEGIN 
    -- Sample data in the (sparse) associative array 
    associativeArray(-2) := 'Test 1'; 
    associativeArray(0) := 'Test 2'; 
    associativeArray(7) := 'Test 3'; 

    -- Initialise the collection 
    array := VARCHAR2_200_Array_Type(); 

    -- Loop through the associative array 
    i := associativeArray.FIRST; 
    WHILE i IS NOT NULL LOOP 
    array.EXTEND(1); 
    array(array.COUNT) := associativeArray(i); 
    i := associativeArray.NEXT(i); 
    END LOOP; 

    -- Use the collection in a query 
    OPEN cur FOR 
    SELECT * 
    FROM your_table 
    WHERE your_column MEMBER OF array; 
END; 
/
Cuestiones relacionadas