La risposta breve è che non puoi. Dovresti definire una variabile per ogni colonna che verrà restituita.
DECLARE
P_RS SYS_REFCURSOR;
L_T_COL1 T.COL1%TYPE;
L_T_COL1 T.COL2%TYPE;
...
E poi vai nell'elenco delle colonne:
FETCH P_RS INTO L_T_COL1, L_T_COL2, ... ;
Questo è doloroso ma gestibile fintanto che sai cosa ti aspetti nel cursore di riferimento. Usando T.*
nella tua procedura lo rende fragile, poiché l'aggiunta di una colonna alla tabella interromperebbe il codice che pensa di sapere quali colonne ci sono e in quale ordine si trovano. (Puoi anche interromperlo tra gli ambienti se le tabelle non sono compilate costantemente - ho visto luoghi in cui l'ordinamento delle colonne è diverso in diversi ambienti). Probabilmente vorrai comunque assicurarti di selezionare solo le colonne che ti interessano veramente, per evitare di dover definire variabili per cose che non leggerai mai.
Da 11g puoi usare il DBMS_SQL
pacchetto per convertire il tuo sys_refcursor
in un DBMS_SQL
cursore e puoi interrogarlo per determinare le colonne. Proprio come esempio di cosa puoi fare, questo stamperà il valore di ogni colonna in ogni riga, con il nome della colonna:
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;
/
Non è di grande utilità pratica e, per brevità, sto trattando ogni valore come una stringa poiché voglio solo stamparlo comunque. Guarda i documenti e cerca esempi per applicazioni più pratiche.
Se vuoi solo poche colonne dal tuo cursore di riferimento potresti, suppongo, girare intorno a l_desc
e registra la posizione in cui column_name
è ciò che ti interessa, come variabile numerica; potresti quindi fare riferimento alla colonna con quella variabile in un secondo momento dove normalmente utilizzeresti il nome in un ciclo del cursore. Dipende da cosa stai facendo con i dati.
Ma a meno che tu non ti stia aspettando di non conoscere l'ordine delle colonne che stai ricevendo, il che è improbabile poiché sembri controllare la procedura e supponendo che ti sbarazzi del .*
s - probabilmente è molto meglio ridurre le colonne restituite al minimo necessario e dichiararle tutte singolarmente.