web-dev-qa-db-ja.com

Oracle関数から完全に動的なテーブルを返す

2つのINパラメータを使用して関数を記述します。最初のパラメータはvarcharで、2番目のパラメータはvarcharsのリストです。これらに基づいて、列の量とタイプvarcharの名前が異なるテーブルを返します。

私が見た限りでは、常にオブジェクト/レコードとそのテーブルタイプを作成する必要があります。これは私のアイデアが機能しないことを意味しますか?基本的な目標は、システムコマンドの出力をテーブルとして呼び出し先に返すことです。

編集:タスクの詳細。 OSコマンドを発行し、出力を消費して、テーブルとして返したいのですが。 OSコマンドからの出力は、CSV形式のデータになります。実行時には、返される行の数はわかりませんが、2番目の引数として渡される列の数しかわかりません。私はJavaを動的STRUCTとそれらを含むARRAYで使用することを考えていました。前者のアプローチを好むでしょうが。

次のようになります。

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
8
Michael-O

かなり複雑ですが、 変数構造を返すパイプラインテーブル関数 を書くことは可能です。パイプラインテーブル関数は2つの引数を取り、Oracle Data CartridgeインターフェイスとAnyDataSetタイプの魔法を使用して、実行時に動的構造を返すことができます。その後、それをテーブルであるかのように、後続のSQLステートメントで使用できます。

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

同じサンプル実装について説明しているさらにいくつかのリファレンス

1
Justin Cave

tmpビューを作成して、ビューを動的に置き換えることができます。

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;

実行結果:

enter image description here

0
Rayika Lao

私はあなたの最善のアプローチは動的テーブルを送り返す試みを放棄することだと思います(私はあなたがmight一時テーブルを作成し、refcursorをそれに戻すことができると思いますが、ここではわかりません) 。

ここでの私の好ましいアプローチは、XML文書などのような、より柔軟な形式で結果を生成し、それを返すことです。これにより、関数のスキャン後に列を決定する必要がなく、必要な柔軟性が得られます。

0
Chris Travers