Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

execute imediato não mostrando registros da instrução Dynamic Select


Como você não conhece a estrutura antecipadamente, devido ao pivô dinâmico para um número desconhecido de colunas no conjunto de resultados, você pode usar um cursor ref para recuperar o resultado da consulta dinâmica.

Isso usa variáveis ​​de ligação 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

A variável variable do cliente comando
variable rc refcursor;

declara a variável e o tipo de dados da variável de ligação do cliente, como um cursor de referência. Então, em vez de usar execute immediate ele abre para com sua declaração dinâmica:
  open :rc for sql_stmt; 

que abre o cursor ref com os resultados dessa consulta. (Observe o : no início de :rc , indicando que é uma referência de variável de ligação e não uma variável PL/SQL local).

Então, fora do bloco, você pode imprimir o conjunto de resultados com:
print rc

Diferentes clientes/IDEs precisarão de sintaxe diferente. Você poderia fazer algo semelhante sobre JDBC também. Você também pode ter uma função que retorna um sys_refcursor . Mas depende de qual é o seu objetivo final para isso.

Aliás, no momento você obterá null para todos os totais pivotados; sua consulta final precisa obter PERIOD_NAME no mesmo formato que a cláusula pivô está procurando, por exemplo
  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 || '))';

embora seja um pouco mais simples deixar o formato original na cláusula pivô:
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;
/

Com uma tabela fictícia e dados:
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;

executando qualquer uma das versões e fazendo print rc mostra:
    JAN-18     FEB-18     MAR-18
---------- ---------- ----------
        42         11         99