Es posible consultar tipos de tablas en PL/SQL, pero solo tablas anidadas y varrays cuyos tipos se declaran a nivel de esquema, es decir, fuera de PL/SQL.
El error
ORA-22905:no se puede acceder a filas desde un elemento de tabla no anidado
significa que está intentando consultar desde un tipo de tabla no compatible. Tu tipo type_tab_AB
es una matriz asociativa, debido al INDEX BY BINARY_INTEGER
cláusula. Eliminar el INDEX BY BINARY_INTEGER
cláusula para hacer su type_tab_AB
un tipo de tabla anidada. (Las matrices Varray también funcionarían aquí, pero no recomendaría usarlas a menos que conozca un límite superior para la cantidad de filas esperadas. Al declarar un tipo Varray, debe especificar la cantidad máxima de elementos, mientras que los tipos de tablas anidadas tienen no hay tal restricción.)
Después de realizar este cambio, es posible que su código aún no funcione. El siguiente error que puede recibir (vea la nota en la parte inferior si no lo hace) es
PLS-00642:tipos de colecciones locales no permitidos en sentencias SQL
Esto se debe a que el tipo que está seleccionando se declara dentro de PL/SQL. Debe declarar type_tab_AB
y record_AB
fuera de PL/SQL, usando CREATE TYPE ...
.
El próximo problema que encuentre será debido a la palabra clave RECORD
. Los tipos de registro solo se pueden crear dentro de PL/SQL, no se pueden crear a nivel de esquema. Cambiar RECORD
a OBJECT
para arreglar esto.
El último problema que encontrará es con SELECT t.AA, t.BB BULK COLLECT INTO tab_AB FROM ...
declaración. Tal como está, esta consulta le dará el siguiente error:
PL/SQL:ORA-00947:no hay suficientes valores
Está seleccionando dos elementos de cada fila y está proporcionando solo una tabla para insertar los datos de forma masiva. Oracle no puede darse cuenta de que desea incluir los dos elementos en su record_AB
tipo. Puede solucionar esto con bastante facilidad cambiando la consulta a SELECT record_AB(t.AA, t.BB) BULK COLLECT INTO tab_AB FROM ...
.
En conjunto, estos cambios deberían solucionar el problema. Aquí hay un script SQL*Plus completo que crea una tabla de prueba con algunos datos de prueba y verifica que puede consultar el tipo de tabla:
CREATE TABLE some_table (AA VARCHAR2(16 BYTE), BB VARCHAR2(16 BYTE));
INSERT INTO some_table (AA, BB) VALUES ('aa 1', 'bb 1');
INSERT INTO some_table (AA, BB) VALUES ('aaaaaaaaaa 2', 'b 2');
INSERT INTO some_table (AA, BB) VALUES ('aaaaa 3', 'bbbbbbbbbbbbbb 3');
COMMIT;
VARIABLE curs REFCURSOR;
CREATE OR REPLACE TYPE record_AB AS OBJECT
(
AA VARCHAR2 (16 BYTE),
BB VARCHAR2 (16 BYTE)
);
/
CREATE OR REPLACE TYPE type_tab_AB IS TABLE OF record_AB;
/
DECLARE
tab_AB type_tab_AB;
BEGIN
SELECT record_AB(t.AA, t.BB)
BULK COLLECT INTO tab_AB
FROM some_table t;
OPEN :curs FOR SELECT * FROM TABLE (tab_AB) ;
END;
/
PRINT :curs
He puesto el resultado de SELECT
ing el contenido de tab_AB
en un cursor y usó una variable de cursor SQL*Plus para listar su contenido. El resultado que obtengo cuando ejecuto el script en Oracle 11g XE, después de todos los mensajes 'Tipo creado' y 'Procedimiento PL/SQL completado con éxito', es el siguiente:
AA BB
---------------- ----------------
aa 1 bb 1
aaaaaaaaaa 2 b 2
aaaaa 3 bbbbbbbbbbbbbb 3
NOTA: Para simplificar, supuse que el autor de la pregunta usa Oracle 11 o anterior. En Oracle 12, creo que puede usar tipos declarados en PL/SQL en una consulta SQL, por lo que es posible que no encuentre el error PLS-00642. No puedo decir qué otros cambios en mi respuesta también podrían ser necesarios para Oracle 12, ya que todavía tengo que usar Oracle 12.