Restituisce una tabella completamente dinamica da una funzione Oracle


8

Vorrei scrivere una funzione con due INparametri in cui il primo è un varchare il secondo un elenco di varchars. Sulla base di questi voglio restituire una tabella con quantità di colonne e nomi di tipo variabili varchar.

Per quanto ho visto, devo sempre creare un oggetto / record e un tipo di tabella. Questo significa che la mia idea non funzionerà? L'obiettivo sottostante è di restituire un comando di sistema in uscita a un chiamato come tabella.

Modifica: ulteriori informazioni sull'attività. Voglio emettere un comando del sistema operativo, utilizzare l'output e restituirlo come tabella. L'output del comando OS sarà formato in formato CSV. Al momento dell'esecuzione non conosco la quantità di righe da restituire, ma solo la quantità di colonne che viene passata come secondo argomento. Stavo pensando di usare Java con una dinamica STRUCTe un ARRAYloro contenimento. Preferirei il primo approccio.

Dovrebbe sembrare come questo:

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

I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
Paul White 9

Risposte:


1

È possibile, sebbene piuttosto complicato, scrivere una funzione di tabella pipeline che restituisce una struttura variabile . La funzione della tabella della pipeline potrebbe accettare i due argomenti e utilizzare l'interfaccia Oracle Data Cartridge e la magia del tipo AnyDataSet per restituire una struttura dinamica in fase di esecuzione. È quindi possibile utilizzarlo nelle successive istruzioni SQL come se fosse una tabella, ad es

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

Un altro paio di riferimenti che parlano della stessa implementazione di esempio


0

Penso che il tuo miglior approccio sia quello di abbandonare il tentativo di rinviare una tabella dinamica (anche se suppongo che potresti essere in grado di creare una tabella temporanea e restituirti un refcoror, ma non sono sicuro qui).

Il mio approccio preferito qui sarebbe quello di generare risultati in un formato più flessibile, qualcosa come un documento XML o simili e restituirlo. Questo ti dà la flessibilità di cui hai bisogno senza dover determinare le colonne dopo la scansione della funzione.


Ciao Chris, grazie per la risposta. Ho già abbandonato la tabella dinamica perché semplicemente non è possibile. XML è troppo dettagliato ma è una buona idea. Il mio problema principale è che avrei bisogno di chiamare una funzione Java statica per interrogare un indice lucene. Ciò significherebbe che devo aprire e chiudere l'indice ogni volta. Questo è molto inefficiente. Ho fatto ricorso a un servizio REST con output JSON e XML.
Michael-O,

0

puoi creare una vista tmp e sostituirla 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;

risultati di esecuzione:

inserisci qui la descrizione dell'immagine


-1

Una soluzione sarebbe quella di creare una tabella estranea basata sull'output di Lucene. Puoi facilmente modificare la definizione della tabella esterna (e puntarla su più file).

Quindi avrai:

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

Funzionerà! La definizione del file è nota e possiamo creare dinamicamente una tabella esterna.
Ohadi,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.