Retornar uma tabela totalmente dinâmica de uma função Oracle

8

Eu gostaria de escrever uma função com dois INparâmetros em que o primeiro é um varchare o segundo uma lista de varchars. Com base nisso, quero retornar uma tabela com valores variáveis ​​de coluna e nomes do tipo varchar.

Tanto quanto eu vi, eu tenho que sempre criar um objeto / registro e um tipo de tabela. Isso significa que minha ideia não vai funcionar? O objetivo subjacente é passar uma saída de comando do sistema de volta para um receptor como uma tabela.

Edit: mais sobre a tarefa. Quero emitir um comando do SO, consumir a saída e retorná-la como uma tabela. A saída do comando do sistema operacional será dados no formato CSV. No momento da execução, não sei a quantidade de linhas a serem retornadas, mas apenas a quantidade de colunas que são passadas como o segundo argumento. Eu estava pensando em usar Java com uma dinâmica STRUCTe em ARRAYcontê-los. Embora eu prefira a abordagem anterior.

Deve ficar assim:

create function(clob query, list of varchars cols) returns table
begin
  execute system command(query, cols);
  examine sysout from command;
  return tabular data from syscmd as table;
end
Michael-O
fonte
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Paul White 9

Respostas:

1

É possível, embora bastante complicado, escrever uma função de tabela em pipeline que retorne uma estrutura variável . Sua função de tabela de pipeline pode usar os dois argumentos e usar a interface do Oracle Data Cartridge e a magia do tipo AnyDataSet para retornar uma estrutura dinâmica em tempo de execução. Você pode usá-lo nas instruções SQL subsequentes como se fosse uma tabela, ou seja,

SELECT *
  FROM TABLE( your_pipelined_function( p_1, p_2 ));

Mais algumas referências que discutem a mesma implementação de amostra

Justin Cave
fonte
0

Acho que sua melhor abordagem é abandonar a tentativa de enviar de volta uma tabela dinâmica (embora suponha que você possa criar uma tabela temporária e devolver um refcursor a ela, mas não tenho certeza aqui).

Minha abordagem preferida aqui seria gerar resultados em um formato mais flexível, algo como um documento XML ou algo semelhante e devolvê-lo. Isso oferece a flexibilidade de que você precisa sem ter que determinar as colunas após a verificação da função.

Chris Travers
fonte
Olá Chris, obrigado pela resposta. Eu já abandonei a tabela dinâmica porque simplesmente não é possível. XML é muito detalhado, mas é uma boa ideia. Meu principal problema é que eu precisaria chamar uma função Java estática para consultar um índice lucene. Isso significa que eu preciso abrir e fechar o índice sempre. Isso é muito ineficiente. Eu recorri a um serviço REST com saída JSON e XML.
Michael-O
0

você pode criar uma visualização tmp e substituir a visualização dinamicamente.

create or replace view tmp_view as select 1 x from dual;
/
create or replace package pkg_input_sql is
  cursor my_cursor is select * from tmp_view;

  my_rec_type my_cursor%rowtype;
  type my_tab_type is table of my_cursor%rowtype;

  function get_cursor(p_sqlstr varchar2) return sys_refcursor;
  function get_table return my_tab_type
    pipelined;

end pkg_input_sql;
/
create or replace package body pkg_input_sql is

  function get_cursor(p_sqlstr varchar2) return sys_refcursor as
    my_cursor sys_refcursor;
  begin
    open my_cursor for p_sqlstr;
    return my_cursor;
  end get_cursor;

  function get_table return my_tab_type
    pipelined is
    my_tab    my_tab_type;
    i         pls_integer;
    my_cursor sys_refcursor;
  begin
    my_cursor := get_cursor('select * from tmp_view');
    fetch my_cursor bulk collect
      into my_tab;
    for i in 1 .. my_tab.count loop
      pipe row(my_tab(i));
    end loop;
  end;

begin
  null;
end pkg_input_sql;
/

create or replace procedure create_tmp_view(p_sqlstr varchar2) is
begin
  execute immediate 'create or replace view tmp_view as ' || p_sqlstr;
  dbms_utility.exec_ddl_statement('alter package pkg_get_sql compile package');
  dbms_session.reset_package; -- to avoid ora-04068
end create_tmp_view;

resultados de execução:

insira a descrição da imagem aqui

Rayika Lao
fonte
-1

Uma solução seria criar uma tabela externa com base na saída do Lucene. Você pode alterar facilmente a definição de tabela externa (e apontá-la para vários arquivos).

Então você terá:

function l_query(clob query, list of varchars cols) returns table_name
begin 
execute system command(query, cols); 
#hopefully we know the output filename
create a new external table mapping the output;
end
Ohadi
fonte
Vai funcionar! A definição do arquivo é conhecida e podemos dinamicamente criar uma tabela externa.
Ohadi