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

Dinâmica da Oracle


Usar sql dinâmico para um resultado em que as colunas são desconhecidas no momento da execução é um pouco trabalhoso no Oracle em comparação com alguns outros RDMBS.

Como o tipo de registro para a saída ainda é desconhecido, ele não pode ser definido antecipadamente.

No Oracle 11g, uma maneira é usar um procedimento sem nome que gera uma tabela temporária com o resultado dinâmico.

Em seguida, selecione os resultados dessa tabela temporária.

declare
  v_sqlqry clob;
  v_cols clob;
begin
  -- Generating a string with a list of the unique names
  select listagg(''''||CCL||''' as "'||CCL||'"', ', ') within group (order by CCL)
  into v_cols
  from 
  (
    select distinct CCL
    from tableA
  );

  -- drop the temporary table if it exists
  EXECUTE IMMEDIATE 'DROP TABLE tmpPivotTableA';
  EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF;

  -- A dynamic SQL to create a temporary table 
  -- based on the results of the pivot
  v_sqlqry := '
    CREATE GLOBAL TEMPORARY TABLE tmpPivotTableA
    ON COMMIT PRESERVE ROWS AS
    SELECT * 
    FROM (SELECT ID, CCL, Flag FROM TableA) src 
    PIVOT (MAX(Flag) FOR (CCL) IN ('||v_cols||')) pvt';

  -- dbms_output.Put_line(v_sqlqry); -- just to check how the sql looks like
  execute immediate v_sqlqry;

end;
/

select * from tmpPivotTableA;

Devoluções:
ID  adam john rob terry
--  ---- ---- --- -----
1   x    x    x
2        x      

Você pode encontrar um teste em db<>fiddle aqui

No Oracle 11g, outro truque legal (criado por Anton Scheffer) para ser usado pode ser encontrado neste blog. Mas você terá que adicionar a função pivot para isso.
O código fonte pode ser encontrado neste zip

Depois disso, o SQL pode ser tão simples quanto isto:
select * from 
table(pivot('SELECT ID, CCL, Flag FROM TableA'));

Você encontrará um teste no db<>fiddle aqui