Oracle
 sql >> Base de données >  >> RDS >> Oracle

exécuter immédiatement sans afficher les enregistrements de l'instruction Dynamic Select

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

La variable variable commande

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