sql >> Databáze >  >> RDS >> Oracle

ORA-22905 - při dotazu na typ tabulky příkazem select

Je možné dotazovat se na typy tabulek v PL/SQL, ale pouze na vnořené tabulky a varraye, jejichž typy jsou deklarovány na úrovni schématu, tj. mimo PL/SQL.

Chyba

ORA-22905:Nelze získat přístup k řádkům z nevnořené položky tabulky

znamená, že se pokoušíte dotazovat z nepodporovaného typu tabulky. Váš typ type_tab_AB je asociativní pole kvůli INDEX BY BINARY_INTEGER doložka. Odstraňte INDEX BY BINARY_INTEGER klauzule k vytvoření vašeho type_tab_AB vnořený typ tabulky. (Varrays by zde také fungovaly, ale nedoporučoval bych je používat, pokud neznáte horní hranici pro počet řádků, které lze očekávat. Při deklaraci typu varray musíte určit maximální počet prvků, zatímco vnořené typy tabulek mají žádné takové omezení.)

Po provedení této změny nemusí váš kód stále fungovat. Další chyba, která se může zobrazit (pokud ne, viz poznámka dole) je

PLS-00642:místní typy kolekcí nejsou povoleny v příkazech SQL

Je to proto, že typ, který vybíráte, je deklarován uvnitř PL/SQL. Musíte deklarovat type_tab_AB a record_AB mimo PL/SQL pomocí CREATE TYPE ... .

Další problém, na který narazíte, bude kvůli klíčovému slovu RECORD . Typy záznamů lze vytvářet pouze uvnitř PL/SQL, nelze je vytvářet na úrovni schématu. Změňte RECORD na OBJECT to opravit.

Poslední problém, na který narazíte, je s SELECT t.AA, t.BB BULK COLLECT INTO tab_AB FROM ... prohlášení. Ve stávající podobě vám tento dotaz zobrazí následující chybu:

PL/SQL:ORA-00947:nedostatek hodnot

Vybíráte dvě položky z každého řádku a poskytujete pouze jednu tabulku pro hromadné vkládání dat. Oracle nemůže tak docela přijít na to, že chcete tyto dvě položky nacpat do vašeho record_AB typ. Můžete to poměrně snadno opravit změnou dotazu na SELECT record_AB(t.AA, t.BB) BULK COLLECT INTO tab_AB FROM ... .

Tyto změny by měly problém vyřešit společně. Zde je úplný skript SQL*Plus, který vytvoří testovací tabulku s některými testovacími daty a ověří, že dokáže zadat dotaz na typ tabulky:

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

Vložil jsem výsledek SELECT ing obsahu tab_AB do kurzoru a pomocí proměnné kurzoru SQL*Plus vypsal její obsah. Výstup, který dostanu, když spustím skript na Oracle 11g XE, po všech zprávách „Typ vytvořen“ a „Procedura PL/SQL úspěšně dokončena“, je následující:

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

POZNÁMKA: Pro jednoduchost jsem předpokládal, že tazatel používá Oracle 11 nebo starší. V Oracle 12 se domnívám, že máte povoleno používat typy deklarované v PL/SQL v dotazu SQL, takže se nemusíte setkat s chybou PLS-00642. Nemohu říci, jaké další změny v mé odpovědi mohou být také nutné pro Oracle 12, protože jsem ještě nepoužil Oracle 12.



  1. Jak vygenerovat náhodné celé číslo v rozsahu v MariaDB

  2. Myšlenky k edicím SQL Server 2019

  3. Nejlepší způsob, jak VLOŽIT mnoho hodnot do mysqli?

  4. Zjistěte typ dat vrácených sloupců v sadě výsledků na serveru SQL Server