sql >> Database >  >> RDS >> Oracle

ORA-22905 - bij het opvragen van een tabeltype met een select-instructie

Het is mogelijk om tabeltypen in PL/SQL op te vragen, maar alleen geneste tabellen en varrays waarvan de typen op schemaniveau zijn gedeclareerd, d.w.z. buiten PL/SQL.

De fout

ORA-22905:geen toegang tot rijen van een niet-genest tabelitem

betekent dat u een query probeert uit te voeren vanuit een niet-ondersteund tabeltype. Jouw type type_tab_AB is een associatieve array, vanwege de INDEX BY BINARY_INTEGER clausule. Verwijder de INDEX BY BINARY_INTEGER clausule om uw type_tab_AB een genest tabeltype. (Varrays zouden hier ook werken, maar ik zou het gebruik ervan niet aanbevelen, tenzij u een bovengrens kent voor het aantal te verwachten rijen. Wanneer u een varray-type declareert, moet u het maximale aantal elementen opgeven, terwijl geneste tabeltypen geen dergelijke beperking.)

Nadat u deze wijziging heeft aangebracht, werkt uw code mogelijk nog steeds niet. De volgende fout die u kunt krijgen (zie opmerking onderaan als u dat niet doet) is

PLS-00642:lokale verzamelingstypen niet toegestaan ​​in SQL-instructies

Dit komt omdat het type waarin u selecteert, wordt gedeclareerd in PL/SQL. U moet type_tab_AB . declareren , en record_AB buiten PL/SQL, met behulp van CREATE TYPE ... .

Het volgende probleem dat u tegenkomt, is het trefwoord RECORD . Recordtypen kunnen alleen binnen PL/SQL worden gemaakt, ze kunnen niet op schemaniveau worden gemaakt. Wijzig RECORD naar OBJECT om dit op te lossen.

Het laatste probleem dat u tegenkomt is met de SELECT t.AA, t.BB BULK COLLECT INTO tab_AB FROM ... uitspraak. Zoals het er nu uitziet, geeft deze query u de volgende foutmelding:

PL/SQL:ORA-00947:niet genoeg waarden

U selecteert twee items uit elke rij en biedt slechts één tabel om de gegevens in bulk in te voegen. Oracle kan er niet helemaal achter komen dat je de twee items in je record_AB wilt stoppen type. U kunt dit vrij eenvoudig oplossen door de query te wijzigen in SELECT record_AB(t.AA, t.BB) BULK COLLECT INTO tab_AB FROM ... .

Gezamenlijk zouden deze wijzigingen het probleem moeten oplossen. Hier is een volledig SQL*Plus-script dat een testtabel maakt met enkele testgegevens en controleert of het het tabeltype kan opvragen:

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

Ik heb het resultaat van SELECT . geplaatst de inhoud van tab_AB in een cursor en gebruikte een SQL*Plus-cursorvariabele om de inhoud ervan weer te geven. De uitvoer die ik krijg als ik het script op Oracle 11g XE uitvoer, na alle berichten 'Type aangemaakt' en 'PL/SQL-procedure succesvol voltooid', is als volgt:

AA               BB
---------------- ----------------
aa 1             bb 1
aaaaaaaaaa 2     b 2
aaaaa 3          bbbbbbbbbbbbbb 3

OPMERKING: Voor de eenvoud heb ik aangenomen dat de vraagsteller Oracle 11 of ouder gebruikt. Ik geloof dat je in Oracle 12 typen mag gebruiken die zijn gedeclareerd in PL/SQL in een SQL-query, zodat je de PLS-00642-fout mogelijk niet tegenkomt. Ik kan niet zeggen welke andere wijzigingen in mijn antwoord ook nodig kunnen zijn voor Oracle 12, aangezien ik Oracle 12 nog moet gebruiken.



  1. Oracle JDBC ojdbc6 Jar als een Maven-afhankelijkheid

  2. Msg 8672, Level 16, State 1, Line 1 De MERGE-instructie heeft meer dan eens geprobeerd dezelfde rij BIJWERKEN of VERWIJDEREN

  3. Een database openen in de exclusieve modus in Access 2016

  4. Hoe koppel ik een hele dag aan een datetime-veld?