Oracle
 sql >> Database >  >> RDS >> Oracle

eseguire immediatamente non mostrando i record dell'istruzione Dynamic Select

Poiché non conosci la struttura in anticipo, a causa del pivot dinamico su un numero sconosciuto di colonne nel set di risultati, puoi utilizzare un cursore di riferimento per recuperare il risultato della query dinamica.

Questo utilizza variabili di collegamento SQL*Plus/SQL Developer/SQLcl;

variable rc refcursor;

declare
  sql_stmt clob; 
  pivot_clause clob; 
begin 
  select listagg('''' || TO_CHAR(PERIOD_NAME,'MON-YY') || ''' as "' || TO_CHAR(PERIOD_NAME,'MON-YY') || '"', ',') 
  within group (order by PERIOD_NAME) 
  into pivot_clause from (select TO_DATE(PERIOD_NAME,'MON-YYYY') PERIOD_NAME 
                          from table1 
                          where request_id=<id> 
                          GROUP BY TO_DATE(PERIOD_NAME,'MON-YYYY') 
                          order by TO_DATE(PERIOD_NAME,'MON-YYYY') ASC); 
  sql_stmt := 'select * from (select PERIOD_NAME, depreciation 
                              from table1) pivot (sum(depreciation) for PERIOD_NAME in (' || pivot_clause || '))';

  open :rc for sql_stmt; 
end;
/

print rc

La client variable comando

variable rc refcursor;

dichiara la variabile e il tipo di dati della variabile di binding client, come cursore di riferimento. Quindi, invece di usare execute immediate fa aperto per con la tua dichiarazione dinamica:

  open :rc for sql_stmt; 

che apre il cursore di riferimento con i risultati di quella query. (Nota il : all'inizio di :rc , indicando che si tratta di un riferimento a una variabile di collegamento e non di una variabile PL/SQL locale).

Quindi fuori dal blocco puoi stampare il risultato impostato con:

print rc

Diversi client/IDE avranno bisogno di una sintassi diversa. Potresti fare qualcosa di simile anche su JDBC. Potresti anche avere una funzione che restituisce un sys_refcursor . Ma dipende dal tuo obiettivo finale per questo.

Per inciso, al momento otterrai un valore nullo per tutti i totali ruotati; la tua query finale deve ottenere PERIOD_NAME nello stesso formato che sta cercando la clausola pivot, ad es.

  sql_stmt := 'select * from (select to_char(to_date(PERIOD_NAME, ''MON-YYYY''), ''MON-YY'') as PERIOD_NAME, depreciation 
                              from table1) pivot (sum(depreciation) for PERIOD_NAME in (' || pivot_clause || '))';

anche se sarebbe leggermente più semplice lasciare invece il formato originale nella clausola pivot:

declare
  sql_stmt clob; 
  pivot_clause clob; 
begin 

  select listagg('''' || PERIOD_NAME || ''' as "' || TO_CHAR(PERIOD_DATE,'MON-YY') || '"', ',') 
  within group (order by PERIOD_DATE) 
  into pivot_clause from (select distinct PERIOD_NAME, TO_DATE(PERIOD_NAME,'MON-YYYY') PERIOD_DATE 
                          from table1 
                          where request_id=<id>); 

  sql_stmt := 'select * from (select PERIOD_NAME, depreciation 
                              from table1) pivot (sum(depreciation) for PERIOD_NAME in (' || pivot_clause || '))';

  open :rc for sql_stmt; 
end;
/

Con una tabella fittizia e dati:

create table table1 (request_id, period_name, depreciation) as
select 1, 'JAN-2018', 42 from dual
union all select 1, 'FEB-2018', 11 from dual
union all select 1, 'MAR-2018', 22 from dual
union all select 1, 'MAR-2018', 33 from dual
union all select 2, 'MAR-2018', 44 from dual;

eseguendo una delle versioni e facendo print rc mostra:

    JAN-18     FEB-18     MAR-18
---------- ---------- ----------
        42         11         99