É possível consultar tipos de tabela em PL/SQL, mas apenas tabelas aninhadas e varrays cujos tipos são declarados no nível do esquema, ou seja, fora da PL/SQL.
O erro
ORA-22905:não é possível acessar linhas de um item de tabela não aninhado
significa que você está tentando consultar de um tipo de tabela não suportado. Seu tipo
type_tab_AB
é um array associativo, por causa do INDEX BY BINARY_INTEGER
cláusula. Remova o INDEX BY BINARY_INTEGER
cláusula para tornar seu type_tab_AB
um tipo de tabela aninhada. (Varrays também funcionariam aqui, mas eu não recomendaria usá-los a menos que você conheça um limite superior para o número de linhas esperado. Ao declarar um tipo varray, você precisa especificar o número máximo de elementos, enquanto os tipos de tabela aninhados têm sem essa restrição.) Depois de fazer essa alteração, seu código ainda pode não funcionar. O próximo erro que você pode receber (veja a nota na parte inferior se não o fizer) é
PLS-00642:tipos de coleta local não permitidos em instruções SQL
Isso ocorre porque o tipo que você está selecionando é declarado dentro do PL/SQL. Você precisa declarar
type_tab_AB
e record_AB
fora do PL/SQL, usando CREATE TYPE ...
. O próximo problema que você encontrar será por causa da palavra-chave
RECORD
. Os tipos de registro só podem ser criados dentro de PL/SQL, eles não podem ser criados no nível do esquema. Alterar RECORD
para OBJECT
para consertar isso. O último problema que você encontrará é com o
SELECT t.AA, t.BB BULK COLLECT INTO tab_AB FROM ...
demonstração. Tal como está, esta consulta lhe dará o seguinte erro:
PL/SQL:ORA-00947:valores insuficientes
Você está selecionando dois itens de cada linha e fornecendo apenas uma tabela para inserir os dados em massa. O Oracle não consegue descobrir que você deseja colocar os dois itens em seu
record_AB
tipo. Você pode corrigir isso facilmente alterando a consulta para SELECT record_AB(t.AA, t.BB) BULK COLLECT INTO tab_AB FROM ...
. Coletivamente, essas alterações devem corrigir o problema. Aqui está um script SQL*Plus completo que cria uma tabela de teste com alguns dados de teste e verifica se pode consultar o tipo de tabela:
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
Coloquei o resultado de
SELECT
o conteúdo de tab_AB
em um cursor e usou uma variável de cursor SQL*Plus para listar seu conteúdo. A saída que recebo quando executo o script no Oracle 11g XE, após todas as mensagens 'Tipo criado' e 'Procedimento PL/SQL concluído com sucesso', é a seguinte:AA BB
---------------- ----------------
aa 1 bb 1
aaaaaaaaaa 2 b 2
aaaaa 3 bbbbbbbbbbbbbb 3
OBSERVAÇÃO: Para simplificar, presumi que o questionador está usando o Oracle 11 ou anterior. No Oracle 12, acredito que você tenha permissão para usar tipos declarados em PL/SQL em uma consulta SQL, portanto, talvez não encontre o erro PLS-00642. Não posso dizer que outras alterações na minha resposta também podem ser necessárias para o Oracle 12, pois ainda não usei o Oracle 12.