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.