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

UNPIVOT em um número indeterminado de colunas


Parece que você deseja não dinamizar a tabela (a dinamização envolveria passar de muitas linhas e 2 colunas para 1 linha com muitas colunas). Você provavelmente precisaria usar SQL dinâmico para gerar a consulta e, em seguida, usar o DBMS_SQL pacote (ou potencialmente EXECUTE IMMEDIATE ) para executá-lo. Você também deve ser capaz de construir uma função de tabela em pipeline que fez o unpivoting. Você também precisaria usar SQL dinâmico dentro da função de tabela em pipeline, mas seria potencialmente menos código. Eu esperaria uma instrução SQL dinâmica pura usando UNPIVOT para ser mais eficiente, no entanto.

Uma abordagem ineficiente, mas relativamente fácil de seguir, seria algo como
SQL> ed
Wrote file afiedt.buf

  1  create or replace type emp_unpivot_type
  2  as object (
  3    empno number,
  4    col   varchar2(4000)
  5* );
SQL> /

Type created.

SQL> create or replace type emp_unpivot_tbl
  2  as table of emp_unpivot_type;
  3  /

Type created.

SQL> ed
Wrote file afiedt.buf

  1  create or replace function unpivot_emp
  2  ( p_empno in number )
  3    return emp_unpivot_tbl
  4    pipelined
  5  is
  6    l_val varchar2(4000);
  7  begin
  8    for cols in (select column_name from user_tab_columns where table_name = 'EMP')
  9    loop
 10      execute immediate 'select ' || cols.column_name || ' from emp where empno = :empno'
 11         into l_val
 12       using p_empno;
 13      pipe row( emp_unpivot_type( p_empno, l_val ));
 14    end loop;
 15    return;
 16* end;
SQL> /

Function created.

Você pode então chamar isso em uma instrução SQL (eu acho que você desejaria pelo menos uma terceira coluna com o nome da coluna)
SQL> ed
Wrote file afiedt.buf

  1  select *
  2*   from table( unpivot_emp( 7934 ))
SQL> /

     EMPNO COL
---------- ----------------------------------------
      7934 7934
      7934 MILLER
      7934 CLERK
      7934 7782
      7934 23-JAN-82
      7934 1301
      7934
      7934 10

8 rows selected.

Uma abordagem mais eficiente seria adaptar a função de tabela em pipeline show_table de Tom Kyte.