sql >> Database teknologi >  >> RDS >> Oracle

ORA-22905 - når du forespørger en tabeltype med en select-sætning

Det er muligt at forespørge tabeltyper i PL/SQL, men kun indlejrede tabeller og varrays, hvis typer er erklæret på skemaniveau, dvs. uden for PL/SQL.

Fejlen

ORA-22905:kan ikke få adgang til rækker fra et ikke-indlejret tabelelement

betyder, at du forsøger at forespørge fra en ikke-understøttet tabeltype. Din type type_tab_AB er en associativ matrix på grund af INDEX BY BINARY_INTEGER klausul. Fjern INDEX BY BINARY_INTEGER klausul for at lave din type_tab_AB en indlejret tabeltype. (Varrays ville også fungere her, men jeg vil ikke anbefale at bruge dem, medmindre du kender en øvre grænse for antallet af rækker, du kan forvente. Når du erklærer en varray-type, skal du angive det maksimale antal elementer, hvorimod indlejrede tabeltyper har ingen sådan begrænsning.)

Når du har foretaget denne ændring, virker din kode muligvis stadig ikke. Den næste fejl du kan få (se note nederst, hvis du ikke gør det) er

PLS-00642:lokale samlingstyper er ikke tilladt i SQL-sætninger

Dette er fordi den type du vælger til er erklæret inde i PL/SQL. Du skal erklære type_tab_AB , og record_AB uden for PL/SQL ved hjælp af CREATE TYPE ... .

Det næste problem, du støder på, vil være på grund af søgeordet RECORD . Posttyper kan kun oprettes inde i PL/SQL, de kan ikke oprettes på skemaniveau. Skift RECORD til OBJECT for at rette dette.

Det sidste problem, du vil støde på, er med SELECT t.AA, t.BB BULK COLLECT INTO tab_AB FROM ... udmelding. Som den står, vil denne forespørgsel give dig følgende fejl:

PL/SQL:ORA-00947:ikke nok værdier

Du vælger to elementer fra hver række og leverer kun én tabel til at masseindsætte dataene i. Oracle kan ikke helt finde ud af, at du vil proppe de to elementer ind i din record_AB type. Du kan løse dette ret nemt ved at ændre forespørgslen til SELECT record_AB(t.AA, t.BB) BULK COLLECT INTO tab_AB FROM ... .

Tilsammen burde disse ændringer løse problemet. Her er et komplet SQL*Plus-script, der opretter en testtabel med nogle testdata og verificerer, at den kan forespørge tabeltypen:

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
 

Jeg har lagt resultatet af SELECT ing af indholdet af tab_AB ind i en markør, og brugte en SQL*Plus-markørvariabel til at liste dens indhold. Outputtet, jeg får, når jeg kører scriptet på Oracle 11g XE, efter alle meddelelserne 'Type oprettet' og 'PL/SQL-procedure gennemført med succes', er som følger:

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

BEMÆRK: For nemheds skyld har jeg antaget, at spørgeren bruger Oracle 11 eller ældre. I Oracle 12 mener jeg, at du har tilladelse til at bruge typer erklæret i PL/SQL i en SQL-forespørgsel, så du kan ikke støde på PLS-00642-fejlen. Jeg kan ikke sige, hvilke andre ændringer af mit svar, der også kan være nødvendige for Oracle 12, da jeg endnu ikke har brugt Oracle 12.



  1. gem install pg --with-pg-config virker, bundt mislykkes

  2. CAST vs ssis dataflow implicit konverteringsforskel

  3. Kørsel af et datavarehus på PostgreSQL

  4. Let til Oracle