Comme vous ne connaissez pas la structure à l'avance, en raison du pivot dynamique vers un nombre inconnu de colonnes dans le jeu de résultats, vous pouvez utiliser un curseur de référence pour récupérer le résultat de la requête dynamique.
Cela utilise des variables de liaison 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
variable rc refcursor;
déclare la variable et le type de données de la variable de liaison client, en tant que curseur de référence. Alors plutôt que d'utiliser execute immediate
il fait ouvrir pour avec votre déclaration dynamique :
open :rc for sql_stmt;
qui ouvre le curseur ref avec les résultats de cette requête. (Remarquez le :
au début de :rc
, indiquant qu'il s'agit d'une référence de variable liée et non d'une variable PL/SQL locale).
Ensuite, en dehors du bloc, vous pouvez imprimer le jeu de résultats avec :
print rc
Différents clients/IDE auront besoin d'une syntaxe différente. Vous pouvez également faire quelque chose de similaire sur JDBC. Vous pouvez également avoir une fonction qui renvoie un sys_refcursor
. Mais cela dépend de votre objectif final.
Incidemment, pour le moment, vous obtiendrez null pour tous les totaux croisés ; votre requête finale doit obtenir PERIOD_NAME
dans le même format que la clause pivot recherche, par exemple
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 || '))';
bien qu'il soit un peu plus simple de laisser le format d'origine dans la clause 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;
/
Avec une table factice et des données :
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;
exécuter l'une ou l'autre version et faire print rc
affiche :
JAN-18 FEB-18 MAR-18
---------- ---------- ----------
42 11 99