Oracle
 sql >> Datenbank >  >> RDS >> Oracle

ORA-22905 – beim Abfragen eines Tabellentyps mit einer Select-Anweisung

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.