Kembalikan tabel yang sepenuhnya dinamis dari fungsi Oracle

8

Saya ingin menulis fungsi dengan dua INparameter di mana yang pertama adalah varchardan yang kedua daftar varchars. Berdasarkan ini saya ingin mengembalikan tabel dengan jumlah kolom dan nama tipe yang bervariasi varchar.

Sejauh yang saya lihat, saya harus selalu membuat objek / catatan dan tipe tabel. Ini berarti bahwa ide saya tidak akan berfungsi? Tujuan yang mendasarinya adalah untuk mengirimkan output perintah sistem kembali ke callee sebagai tabel.

Edit: lebih lanjut tentang tugas. Saya ingin mengeluarkan perintah OS, mengkonsumsi output dan mengembalikannya sebagai tabel. Output dari perintah OS akan menjadi data yang diformat CSV. Pada saat eksekusi saya tidak tahu jumlah baris yang akan dikembalikan tetapi hanya jumlah kolom yang dilewati sebagai argumen kedua. Saya sedang berpikir tentang menggunakan Java dengan dinamis STRUCTdan ARRAYmengandung mereka. Meskipun saya lebih suka pendekatan yang pertama.

Seharusnya terlihat seperti ini:

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
sumber
Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
Paul White 9

Jawaban:

1

Dimungkinkan, meskipun cukup rumit, untuk menulis fungsi tabel pipelined yang mengembalikan struktur variabel . Fungsi tabel pipa Anda bisa mengambil dua argumen dan menggunakan antarmuka Oracle Data Cartridge dan keajaiban tipe AnyDataSet untuk mengembalikan struktur dinamis saat runtime. Anda kemudian dapat menggunakannya dalam pernyataan SQL berikutnya seolah-olah itu adalah sebuah tabel, yaitu

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

Sepasang lagi referensi yang membahas implementasi sampel yang sama

Gua Justin
sumber
0

Saya pikir pendekatan terbaik Anda adalah mengabaikan upaya untuk mengirim kembali tabel dinamis (walaupun saya kira Anda mungkin dapat membuat tabel sementara dan mengembalikan refcursor ke sana, tapi saya tidak yakin di sini).

Pendekatan pilihan saya di sini adalah menghasilkan hasil dalam format yang lebih fleksibel, seperti dokumen XML atau sejenisnya dan mengembalikannya. Ini memberi Anda fleksibilitas yang Anda butuhkan tanpa harus menentukan kolom setelah pemindaian fungsi.

Chris Travers
sumber
Hai Chris, terima kasih atas jawabannya. Saya sudah meninggalkan tabel dinamis karena itu tidak mungkin. XML terlalu bertele-tele tetapi ide yang bagus. Masalah utama saya adalah bahwa saya perlu memanggil fungsi Java statis untuk meminta indeks lucene. Ini berarti bahwa saya harus membuka dan menutup indeks setiap saat. Ini sangat tidak efisien. Saya telah menggunakan layanan REST dengan output JSON dan XML.
Michael-O
0

Anda dapat membuat tampilan tmp, dan mengganti tampilan secara dinamis.

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;

hasil eksekusi:

masukkan deskripsi gambar di sini

Rayika Lao
sumber
-1

Salah satu solusinya adalah membuat tabel ekstra berdasarkan pada keluaran Lucene. Anda dapat dengan mudah mengubah definisi tabel eksternal (dan mengarahkannya ke beberapa file).

Jadi, Anda akan memiliki:

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
sumber
Itu akan berhasil! Definisi file diketahui dan kita secara dinamis dapat membuat tabel eksternal.
Ohadi