Es ist möglich, Tabellentypen in PL/SQL abzufragen, aber nur verschachtelte Tabellen und Varrays, deren Typen auf Schemaebene deklariert werden, d. h. außerhalb von PL/SQL.
Der Fehler
ORA-22905:Kein Zugriff auf Zeilen eines nicht verschachtelten Tabellenelements
bedeutet, dass Sie versuchen, einen nicht unterstützten Tabellentyp abzufragen. Ihr Typ type_tab_AB
ist aufgrund des INDEX BY BINARY_INTEGER
ein assoziatives Array Klausel. Entfernen Sie den INDEX BY BINARY_INTEGER
-Klausel, um Ihr type_tab_AB
zu erstellen ein verschachtelter Tabellentyp. (Varrays würden hier auch funktionieren, aber ich würde nicht empfehlen, sie zu verwenden, es sei denn, Sie kennen eine Obergrenze für die Anzahl der zu erwartenden Zeilen. Wenn Sie einen varray-Typ deklarieren, müssen Sie die maximale Anzahl von Elementen angeben, während verschachtelte Tabellentypen dies tun müssen keine solche Einschränkung.)
Nachdem Sie diese Änderung vorgenommen haben, funktioniert Ihr Code möglicherweise immer noch nicht. Der nächste Fehler, den Sie möglicherweise erhalten (siehe Hinweis unten, falls nicht), ist
PLS-00642:Lokale Sammlungstypen sind in SQL-Anweisungen nicht zulässig
Dies liegt daran, dass der Typ, den Sie auswählen, in PL/SQL deklariert ist. Sie müssen type_tab_AB
deklarieren und record_AB
außerhalb von PL/SQL mit CREATE TYPE ...
.
Das nächste Problem, auf das Sie stoßen, wird wegen des Schlüsselworts RECORD
auftreten . Datensatztypen können nur innerhalb von PL/SQL erstellt werden, sie können nicht auf Schemaebene erstellt werden. Ändere RECORD
zu OBJECT
um dies zu beheben.
Das letzte Problem, auf das Sie stoßen werden, ist mit SELECT t.AA, t.BB BULK COLLECT INTO tab_AB FROM ...
Erklärung. So wie es aussieht, gibt diese Abfrage den folgenden Fehler aus:
PL/SQL:ORA-00947:nicht genügend Werte
Sie wählen zwei Elemente aus jeder Zeile aus und stellen nur eine Tabelle bereit, in die die Daten per Bulk-Einfügung eingefügt werden können. Oracle kann sich nicht ganz vorstellen, dass Sie die beiden Elemente in Ihren record_AB
stopfen möchten Typ. Sie können dies ziemlich einfach beheben, indem Sie die Abfrage in SELECT record_AB(t.AA, t.BB) BULK COLLECT INTO tab_AB FROM ...
ändern .
Zusammen sollten diese Änderungen das Problem beheben. Hier ist ein vollständiges SQL*Plus-Skript, das eine Testtabelle mit einigen Testdaten erstellt und überprüft, ob es den Tabellentyp abfragen kann:
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
Ich habe das Ergebnis von SELECT
eingefügt den Inhalt von tab_AB
ändern in einen Cursor und verwendete eine SQL*Plus-Cursorvariable, um ihren Inhalt aufzulisten. Die Ausgabe, die ich erhalte, wenn ich das Skript auf Oracle 11g XE ausführe, nachdem alle Meldungen „Typ erstellt“ und „PL/SQL-Prozedur erfolgreich abgeschlossen“ angezeigt wurden, lautet wie folgt:
AA BB
---------------- ----------------
aa 1 bb 1
aaaaaaaaaa 2 b 2
aaaaa 3 bbbbbbbbbbbbbb 3
HINWEIS: Der Einfachheit halber bin ich davon ausgegangen, dass der Fragesteller Oracle 11 oder älter verwendet. Ich glaube, dass Sie in Oracle 12 in PL/SQL deklarierte Typen in einer SQL-Abfrage verwenden dürfen, sodass der Fehler PLS-00642 möglicherweise nicht auftritt. Ich kann nicht sagen, welche anderen Änderungen an meiner Antwort möglicherweise auch für Oracle 12 erforderlich sind, da ich Oracle 12 noch verwenden muss.