Si queremos especificar el valor en el índice de una matriz asociativa entonces tenemos que utilizar esta sintaxis:
SQL> declare
2 type n_array is table of varchar2(30)
3 index by binary_integer;
4 emp_names n_array;
5 begin
6 for r in (select ename, empno from emp)
7 loop
8 emp_names(r.empno) := r.ename;
9 end loop;
10
11 dbms_output.put_line('count='||emp_names.count()
12 ||'::last='||emp_names.last());
13 dbms_output.put_line(emp_names(8085));
14
15 end;
16/
count=19::last=8085
TRICHLER
PL/SQL procedure successfully completed.
SQL>
Nos puede poblar matrices asociativas con recopilación masiva, pero solo si el índice es un número entero, y nos complace indexar (implícitamente) ROWNUM, es decir, no una clave dispersa ...
SQL> declare
2 type n_array is table of varchar2(30)
3 index by binary_integer;
4 emp_names n_array;
5 begin
6 select ename
7 bulk collect into emp_names
8 from emp ;
9
10 dbms_output.put_line('count='||emp_names.count()
11 ||'::last='||emp_names.last());
12 dbms_output.put_line(emp_names(19));
13
14 end;
15/
count=19::last=19
FEUERSTEIN
PL/SQL procedure successfully completed.
SQL>
Para ser justos, si necesita utilizar BULK COLLECT probablemente esté tratando con más datos de los apropiados para una matriz asociativa.
Editar
Una prueba de rendimiento económico-ish de los dos enfoques:
SQL> declare
2 type n_array is table of varchar2(30)
3 index by binary_integer;
4 emp_names n_array;
5 s_time pls_integer;
6 e_time pls_integer;
7 begin
8 s_time := dbms_utility.get_time;
9 select ename
10 bulk collect into emp_names
11 from big_emp
12 where rownum <= 500;
13 dbms_output.put_line('bulk collect elapsed time = '
14 ||to_char(dbms_utility.get_time - s_time));
15 s_time := dbms_utility.get_time;
16 for r in (select ename, empno from big_emp
17 where rownum <= 500)
18 loop
19 emp_names(r.empno) := r.ename;
20 end loop;
21 dbms_output.put_line('sparse array elapsed time = '
22 ||to_char(dbms_utility.get_time - s_time));
23 end;
24/
bulk collect elapsed time = 0
sparse array elapsed time = 0
PL/SQL procedure successfully completed.
SQL>
pruebas de rendimiento del reloj de pared son notoriamente chungo. Pero para unos cientos de registros, no es probable que valga la pena preocuparse por ninguna diferencia, sin duda en el contexto del tipo de lugar en el que podríamos querer usar una matriz asociativa.
Editar 2
@ Dan dijo:
t parece a mí que querer consultar un número tamaño decente de filas en una estructura de datos que se puede utilizar para constante- búsqueda de tiempo debe ser una bastante común necesidad
Realmente depende de su definición de "un número de tamaño decente". ¿De verdad hay muchos casos en los que nos gustaría poblar una matriz asociativa con miles de filas, con un índice de cadena? Cuando llegamos a ese tipo de números, una tabla de base de datos normal puede ser igual de útil, especialmente en 11g Enterprise Edition with resultset caching.
+1. Si el número de filas es (o alguna vez será) muy grande, considere usar una cláusula LIMIT para evitar el consumo excesivo de memoria PGA. –
Sí, también hago eso para permitir una mejor escala. Aunque pensé que sería un poco exagerado. –