E 'possibile interrogare tipi di tabella di PL/SQL, ma solo le tabelle nidificate e varrays i cui tipi sono dichiarati a livello di schema-, vale a dire al di fuori di PL/SQL.
L'errore
ORA-22905: cannot access rows from a non-nested table item
significa che si sta tentando di eseguire query da un tipo di tabella non supportato. Il tuo tipo type_tab_AB
è un array associativo, a causa della clausola INDEX BY BINARY_INTEGER
. Rimuovi la clausola INDEX BY BINARY_INTEGER
per rendere il tuo type_tab_AB
un tipo di tabella nidificato. (Anche i Varrays funzionerebbero qui, ma non consiglierei di usarli a meno che non si conosca un limite superiore per il numero di righe da aspettarsi.Quando si dichiara un tipo varray, è necessario specificare il numero massimo di elementi, mentre i tipi di tabella annidati hanno nessuna restrizione.)
Dopo aver apportato questa modifica, il codice potrebbe non funzionare. Il prossimo errore si può ottenere (vedi nota in fondo, se non) è
PLS-00642: local collection types not allowed in SQL statements
Questo perché il tipo si sta selezionando in è dichiarata all'interno PL/SQL. È necessario dichiarare type_tab_AB
e record_AB
al di fuori di PL/SQL, utilizzando CREATE TYPE ...
.
Il prossimo problema riscontrato sarà dovuto alla parola chiave RECORD
. I tipi di record possono essere creati solo all'interno di PL/SQL, they cannot be created at schema level. Modificare RECORD
a OBJECT
per risolvere questo problema.
L'ultimo problema riscontrato è con la dichiarazione SELECT t.AA, t.BB BULK COLLECT INTO tab_AB FROM ...
. Così com'è, questa query vi darà il seguente errore:
PL/SQL: ORA-00947: not enough values
Si sta selezionando due elementi di ogni riga e stanno fornendo un solo tavolo di massa-inserire i dati in. Oracle non riesce a capire che vuoi inserire i due articoli nel tuo tipo record_AB
. Puoi sistemarlo abbastanza facilmente cambiando la query in SELECT record_AB(t.AA, t.BB) BULK COLLECT INTO tab_AB FROM ...
.
Collettivamente queste modifiche dovrebbero risolvere il problema. Ecco uno SQL * completo più script che crea una tabella di test con alcuni dati di prova e verifica che si può interrogare il tipo di tabella:
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
ho messo il risultato di SELECT
ing i contenuti di tab_AB
in un cursore, e ha utilizzato una variabile del cursore SQL * Plus per elencarne il contenuto.L'uscita ottengo quando faccio funzionare lo scritto su Oracle 11g XE, dopo tutte le 'Tipo creato' e 'procedure PL/SQL completata con successo' messaggi, è la seguente:
AA BB
---------------- ----------------
aa 1 bb 1
aaaaaaaaaa 2 b 2
aaaaa 3 bbbbbbbbbbbbbb 3
NOTA: Per semplicità , Ho ipotizzato che l'interrogante stia usando Oracle 11 o precedente. In Oracle 12, credo che sia consentito utilizzare i tipi dichiarati in PL/SQL in una query SQL, quindi non si può incontrare l'errore PLS-00642. Non posso dire quali altre modifiche alla mia risposta potrebbero essere necessarie anche per Oracle 12 poiché non ho ancora utilizzato Oracle 12.
Penso che questo abbia bisogno di più contesto. Puoi pubblicare un esempio minimo _complete_ che dimostra questo errore? Devi compilare 'tab_AB' con più record nella tua procedura affinché questo funzioni, in questo caso perché stai selezionando questa variabile. – Ben