sql >> Databasteknik >  >> RDS >> Oracle

hur deklarerar man %ROWTYPE för en variabel som är en svagt skriven SYS_REFCURSOR?

Det korta svaret är att du inte kan. Du måste definiera en variabel för varje kolumn som ska returneras.

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

Och hämta sedan till listan med kolumner:

FETCH P_RS INTO L_T_COL1, L_T_COL2, ... ;

Detta är smärtsamt men hanterbart så länge du vet vad du förväntar dig i ref-markören. Använder T.* i din procedur gör detta dock bräckligt, eftersom att lägga till en kolumn i tabellen skulle bryta koden som tror att den vet vilka kolumner som finns och vilken ordning de är i. (Du kan också bryta den mellan miljöer om tabellerna inte är byggda konsekvent - jag har sett platser där kolumnordningen är olika i olika miljöer). Du vill förmodligen se till att du bara väljer de kolumner som du verkligen bryr dig om, för att undvika att behöva definiera variabler för saker du aldrig kommer att läsa.

Från 11g kan du använda DBMS_SQL paket för att konvertera din sys_refcursor till en DBMS_SQL markören, och du kan fråga den för att bestämma kolumnerna. Bara som ett exempel på vad du kan göra, kommer detta att skriva ut värdet för varje kolumn i varje rad, med kolumnnamnet:

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

Det är inte till mycket praktisk användning, och för korthetens skull behandlar jag varje värde som en sträng eftersom jag bara vill skriva ut det ändå. Titta på dokumenten och sök efter exempel för mer praktiska tillämpningar.

Om du bara vill ha ett fåtal kolumner från din referensmarkör kan du, antar jag, gå runt l_desc och registrera positionen där column_name är vad du än är intresserad av, som en numerisk variabel; du kan sedan referera till kolumnen med den variabeln senare där du normalt skulle använda namnet i en markörslinga. Beror på vad du gör med datan.

Men om du inte förväntar dig att inte veta vilken kolumnordning du får tillbaka, vilket är osannolikt eftersom du verkar kontrollera proceduren - och förutsatt att du blir av med .* s - du är förmodligen mycket bättre av att minska de returnerade kolumnerna till det minimum du behöver och bara deklarera dem alla individuellt.




  1. Vad motsvarar LISTAGG (Oracle-databas) i PostgreSQL?

  2. Hur man installerar SQL Server på Linux

  3. Lägga till flera kolumner EFTER en specifik kolumn i MySQL

  4. Hur ska jag importera data från CSV till en Postgres-tabell med pgAdmin 3?