sql >> Database >  >> RDS >> Oracle

hoe %ROWTYPE declareren van een variabele die een zwak getypte SYS_REFCURSOR is?

Het korte antwoord is:dat kan niet. U moet een variabele definiëren voor elke kolom die wordt geretourneerd.

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

En dan ophalen in de lijst met kolommen:

FETCH P_RS INTO L_T_COL1, L_T_COL2, ... ;

Dit is pijnlijk maar beheersbaar zolang je weet wat je verwacht in de ref-cursor. Met behulp van T.* in uw procedure maakt dit echter kwetsbaar, omdat het toevoegen van een kolom aan de tabel de code zou breken die denkt te weten welke kolommen er zijn en in welke volgorde ze zich bevinden. (U kunt het ook tussen omgevingen doorbreken als de tabellen niet zijn gebouwd consistent - ik heb plaatsen gezien waar de volgorde van kolommen in verschillende omgevingen anders is). U wilt er waarschijnlijk zeker van zijn dat u alleen de kolommen selecteert die u echt belangrijk vindt, om te voorkomen dat u variabelen moet definiëren voor dingen die u nooit zult lezen.

Vanaf 11g kunt u de DBMS_SQL . gebruiken pakket om uw sys_refcursor . te converteren in een DBMS_SQL cursor, en u kunt die ondervragen om de kolommen te bepalen. Als voorbeeld van wat u kunt doen, wordt de waarde van elke kolom in elke rij afgedrukt, met de kolomnaam:

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;
/

Dat heeft niet veel praktisch nut, en kortheidshalve behandel ik elke waarde als een tekenreeks, omdat ik het toch gewoon wil afdrukken. Bekijk de documenten en zoek naar voorbeelden voor meer praktische toepassingen.

Als je maar een paar kolommen van je ref-cursor wilt, zou je, denk ik, rond l_desc kunnen lopen en noteer de positie waar column_name is alles waarin je geïnteresseerd bent, als een numerieke variabele; je zou dan later met die variabele naar de kolom kunnen verwijzen waar je normaal gesproken de naam in een cursorlus zou gebruiken. Hangt ervan af wat je met de gegevens doet.

Maar tenzij je verwacht om de kolomvolgorde niet te kennen die u terugkrijgt, wat onwaarschijnlijk is aangezien u de procedure lijkt te beheersen - en ervan uitgaande dat u de .* verwijdert s - het is waarschijnlijk veel beter om de geretourneerde kolommen te verminderen tot het minimum dat u nodig hebt en ze allemaal afzonderlijk te declareren.




  1. Sessietijdzone instellen met spring jdbc oracle

  2. Hoe een afbeelding in de kamerpersistentiebibliotheek invoegen?

  3. Hoe meerdere waarden in één kolom te retourneren (T-SQL)?

  4. Hoe een gegevenstabel invoegen in de SQL Server-databasetabel?