sql >> Databasteknik >  >> RDS >> Oracle

ORA-22905 - när du frågar en tabelltyp med en select-sats

Det är möjligt att fråga tabelltyper i PL/SQL, men bara kapslade tabeller och varrayer vars typer deklareras på schemanivå, dvs utanför PL/SQL.

Felet

ORA-22905:kan inte komma åt rader från ett icke-kapslat tabellobjekt

betyder att du försöker fråga från en tabelltyp som inte stöds. Din typ type_tab_AB är en associativ array, på grund av INDEX BY BINARY_INTEGER klausul. Ta bort INDEX BY BINARY_INTEGER sats för att göra din type_tab_AB en kapslad tabelltyp. (Varrayer skulle också fungera här, men jag skulle inte rekommendera att använda dem om du inte vet en övre gräns för antalet rader som kan förväntas. När du deklarerar en varray-typ måste du ange det maximala antalet element, medan kapslade tabelltyper har ingen sådan begränsning.)

Efter att ha gjort denna ändring kanske din kod fortfarande inte fungerar. Nästa fel du kan få (se notering längst ner om du inte gör det) är

PLS-00642:lokala samlingstyper är inte tillåtna i SQL-satser

Detta beror på att typen du väljer deklareras i PL/SQL. Du måste deklarera type_tab_AB och record_AB utanför PL/SQL, med CREATE TYPE ... .

Nästa problem du stöter på kommer att bero på nyckelordet RECORD . Posttyper kan bara skapas i PL/SQL, de kan inte skapas på schemanivå. Ändra RECORD till OBJECT för att fixa detta.

Det sista problemet du kommer att stöta på är med SELECT t.AA, t.BB BULK COLLECT INTO tab_AB FROM ... påstående. Som det ser ut kommer denna fråga att ge dig följande fel:

PL/SQL:ORA-00947:inte tillräckligt med värden

Du väljer två objekt från varje rad och tillhandahåller endast en tabell att massinsätta data i. Oracle kan inte riktigt lista ut att du vill stoppa in de två objekten i din record_AB typ. Du kan rätta till detta ganska enkelt genom att ändra frågan till SELECT record_AB(t.AA, t.BB) BULK COLLECT INTO tab_AB FROM ... .

Tillsammans borde dessa ändringar lösa problemet. Här är ett fullständigt SQL*Plus-skript som skapar en testtabell med vissa testdata och verifierar att den kan fråga efter tabelltypen:

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

Jag har lagt resultatet av SELECT ing innehållet i tab_AB till en markör och använde en SQL*Plus markörvariabel för att lista dess innehåll. Utdata som jag får när jag kör skriptet på Oracle 11g XE, efter alla meddelanden 'Typ skapad' och 'PL/SQL-proceduren har slutförts framgångsrikt', är följande:

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

OBS: För enkelhetens skull har jag antagit att frågeställaren använder Oracle 11 eller äldre. I Oracle 12 tror jag att du får använda typer som deklarerats i PL/SQL i en SQL-fråga, så du kanske inte stöter på PLS-00642-felet. Jag kan inte säga vilka andra ändringar i mitt svar som också kan vara nödvändiga för Oracle 12 eftersom jag ännu inte har använt Oracle 12.



  1. Hur man subtraherar en dag från ett datum i MariaDB

  2. Hur man designar en resewebbplatsdatabas

  3. Lagring av SQLite-databas med Android och Phonegap

  4. Ansluter till Informix (IDS12 DB) i IRI Workbench