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

jak deklarovat %ROWTYPE proměnné, která má slabý typ SYS_REFCURSOR?

Krátká odpověď je, nemůžete. Pro každý sloupec, který bude vrácen, budete muset definovat proměnnou.

DECLARE
    P_RS SYS_REFCURSOR;
    L_T_COL1 T.COL1%TYPE;
    L_T_COL1 T.COL2%TYPE;
    ...

A pak načtěte do seznamu sloupců:

FETCH P_RS INTO L_T_COL1, L_T_COL2, ... ;

To je bolestivé, ale zvládnutelné, pokud víte, co v referenčním kurzoru očekáváte. Pomocí T.* ve vašem postupu je to však křehké, protože přidání sloupce do tabulky by narušilo kód, který si myslí, že ví, jaké sloupce tam jsou a v jakém jsou pořadí. (Můžete to také rozdělit mezi prostředími, pokud tabulky nejsou vytvořeny konzistentně - viděl jsem místa, kde se řazení sloupců v různých prostředích liší). Pravděpodobně se budete chtít ujistit, že vybíráte pouze sloupce, které vás opravdu zajímají, abyste nemuseli definovat proměnné pro věci, které nikdy nečtete.

Od 11g můžete používat DBMS_SQL balíček pro převod vašeho sys_refcursor do DBMS_SQL kurzor a můžete to zjistit, abyste určili sloupce. Jako příklad toho, co můžete udělat, se vytiskne hodnota každého sloupce v každém řádku s názvem sloupce:

DECLARE
    P_RS SYS_REFCURSOR;
    L_COLS NUMBER;
    L_DESC DBMS_SQL.DESC_TAB;
    L_CURS INTEGER;
    L_VARCHAR VARCHAR2(4000);
BEGIN
    CAPITALEXTRACT(P_RS => P_RS);
    L_CURS := DBMS_SQL.TO_CURSOR_NUMBER(P_RS);
    DBMS_SQL.DESCRIBE_COLUMNS(C => L_CURS, COL_CNT => L_COLS,
        DESC_T => L_DESC);

    FOR i IN 1..L_COLS LOOP
        DBMS_SQL.DEFINE_COLUMN(L_CURS, i, L_VARCHAR, 4000);
    END LOOP;

    WHILE DBMS_SQL.FETCH_ROWS(L_CURS) > 0 LOOP
        FOR i IN 1..L_COLS LOOP
            DBMS_SQL.COLUMN_VALUE(L_CURS, i, L_VARCHAR);
            DBMS_OUTPUT.PUT_LINE('Row ' || DBMS_SQL.LAST_ROW_COUNT
                || ': ' || l_desc(i).col_name
                || ' = ' || L_VARCHAR);
        END LOOP;
    END LOOP;

    DBMS_SQL.CLOSE_CURSOR(L_CURS);
END;
/

To není příliš praktické použití a pro stručnost zacházím s každou hodnotou jako s řetězcem, protože ji chci stejně vytisknout. Podívejte se na dokumenty a vyhledejte příklady pro praktičtější aplikace.

Pokud chcete z referenčního kurzoru jen několik sloupců, mohli byste, předpokládám, zacyklit kolem l_desc a zaznamenejte pozici, kde je column_name je cokoli, co vás zajímá, jako číselná proměnná; pak byste mohli později odkazovat na sloupec touto proměnnou, kde byste normálně použili název v kurzorové smyčce. Záleží, co s daty děláte.

Ale pokud neočekáváte neznáte pořadí sloupců, které dostáváte zpět, což je nepravděpodobné, protože se zdá, že postup ovládáte - a za předpokladu, že se zbavíte .* s – pravděpodobně mnohem lépe zredukujete vrácené sloupce na minimum, které potřebujete, a deklarujete je všechny jednotlivě.




  1. cx oracle ImportError

  2. Odeberte všechny mezery z řetězce na serveru SQL Server

  3. Funkce LOG() v Oracle

  4. Získejte záznamy s maximální hodnotou pro každou skupinu seskupených výsledků SQL