Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

ORA-22905 - ao consultar um tipo de tabela com uma instrução select


É 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.