2011-08-10 49 views
89

Me gustaría crear una variable de matriz en memoria que pueda usarse en mi código PL/SQL. No puedo encontrar ninguna colección en Oracle PL/SQL que use memoria pura, todas parecen estar asociadas con tablas. Estoy mirando para hacer algo como esto en mi PL/SQL (# sintaxis de C):Oracle PL/SQL - ¿Cómo crear una variable de matriz simple?

string[] arrayvalues = new string[3] {"Matt", "Joanne", "Robert"}; 

Editar: Oracle: 9i

+2

Ver: [PL/SQL y Colecciones Records] (http://download.oracle.com/docs/cd/B10501_01/appdev .920/a96624/05_colls.htm # 1059) – user272735

+1

La referencia de "tabla" tiende a ser una resaca de las antiguas tablas PL/SQL. Los VARRAY, las matrices asociativas y las tablas anidadas declaradas son todos tipos de matrices en memoria. – Ollie

+0

lea este enlace http://www.orafaq.com/wiki/VARRAY y http: //www.dba-oracle.com/tips_oracle_varray.htm – zloctb

Respuesta

178

Usted puede utilizar VARRAY para una matriz de tamaño fijo:

declare 
    type array_t is varray(3) of varchar2(10); 
    array array_t := array_t('Matt', 'Joanne', 'Robert'); 
begin 
    for i in 1..array.count loop 
     dbms_output.put_line(array(i)); 
    end loop; 
end; 

o una mesa para una serie ilimitada:

... 
    type array_t is table of varchar2(10); 
... 

La palabra "tabla" aquí no tiene nada que ver con las tablas de la base de datos, de manera confusa. Ambos métodos crean matrices en memoria.

Con cualquiera de estos que tanto necesita para inicializar y ampliar la colección antes de añadir elementos:

declare 
    type array_t is varray(3) of varchar2(10); 
    array array_t := array_t(); -- Initialise it 
begin 
    for i in 1..3 loop 
     array.extend(); -- Extend it 
     array(i) := 'x'; 
    end loop; 
end; 

El primer índice es 1 no 0.

+37

"confusamente" casi resume Oracle –

+0

¿Lo inserto en las tablas de la misma manera que las matrices? es decir 'my_array (0): = 'some string';' – Abdul

+1

@Abdul See updated answer. –

50

Se podía declarar una DBMS_SQL.VARCHAR2_TABLE para mantener una en memoria matriz de longitud variable referenciado por un BINARY_INTEGER:

DECLARE 
    name_array dbms_sql.varchar2_table; 
BEGIN 
    name_array(1) := 'Tim'; 
    name_array(2) := 'Daisy'; 
    name_array(3) := 'Mike'; 
    name_array(4) := 'Marsha'; 
    -- 
    FOR i IN name_array.FIRST .. name_array.LAST 
    LOOP 
     -- Do something 
    END LOOP; 
END; 

se podría utilizar un array asociativo (que antes se llamaba mesas PL/SQL) ya que son una array en memoria.

DECLARE 
    TYPE employee_arraytype IS TABLE OF employee%ROWTYPE 
     INDEX BY PLS_INTEGER; 
    employee_array employee_arraytype; 
BEGIN 
    SELECT * 
    BULK COLLECT INTO employee_array 
    FROM employee 
    WHERE department = 10; 
    -- 
    FOR i IN employee_array.FIRST .. employee_array.LAST 
    LOOP 
     -- Do something 
    END LOOP; 
END; 

La matriz asociativa puede contener cualquier composición de tipos de registro.

Espero que ayude, Ollie.

+3

Esto se suma a la respuesta de Tony anterior, que es una buena respuesta ... – Ollie

+11

La condición de iteración aumenta 'VALOR_ERROR' cuando la colección está vacía. Sugeriría usar 'FOR i IN 1 .. employee_array.COUNT' en este caso – unziberla

4

También puede utilizar un oracle defined collection

DECLARE 
    arrayvalues sys.odcivarchar2list; 
BEGIN 
    arrayvalues := sys.odcivarchar2list('Matt','Joanne','Robert'); 
    FOR x IN (SELECT m.column_value m_value 
       FROM table(arrayvalues) m) 
    LOOP 
    dbms_output.put_line (x.m_value||' is a good pal'); 
    end loop; 
END; 

me gustaría utilizar matriz en memoria. Pero con la .COUNT mejora sugerida por uziberia:

DECLARE 
    TYPE t_people IS TABLE OF varchar2(10); 
    INDEX BY PLS_INTEGER; 
    arrayvalues t_people; 
BEGIN 
    SELECT * 
    BULK COLLECT INTO arrayvalues 
    FROM (select 'Matt' m_value from dual union all 
     select 'Joanne'  from dual union all 
     select 'Robert'  from dual 
    ) 
    ; 
    -- 
    FOR i IN 1 .. arrayvalues.COUNT 
    LOOP 
    dbms_output.put_line(arrayvalues(i)||' is my friend'); 
    END LOOP; 
END; 

Otra solución sería utilizar un Hashmap como @Jchomel here

NB:

Con Oracle 12c puede even query arrays directly now!

6

Otra solución es utilizar una colección de Oracle como un Hashmap:

declare 
-- create a type for your "Array" - it can be of any kind, record might be useful 
    type hash_map is table of varchar2(1000) index by varchar2(30); 
    my_hmap hash_map ; 
-- i will be your iterator: it must be of the index's type 
    i varchar2(30); 
begin 
    my_hmap('a') := 'apple'; 
    my_hmap('b') := 'box'; 
    my_hmap('c') := 'crow'; 
-- then how you use it: 

    dbms_output.put_line (my_hmap('c')) ; 

-- or to loop on every element - it's a "collection" 
    i := my_hmap.FIRST; 

    while (i is not null) loop  
    dbms_output.put_line(my_hmap(i));  
    i := my_hmap.NEXT(i); 
    end loop; 

end; 
Cuestiones relacionadas