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


8

IN最初のパラメータがa varcharで、2番目のパラメータがのリストである2つのパラメータを持つ関数を書きたいのvarcharsですが。これらに基づいて、列の量と型の名前が異なるテーブルを返しますvarchar

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

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

次のようになります。

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

コメントは詳細な議論のためのものではありません。この会話はチャットに移動しました
ポールホワイト9

回答:


1

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

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

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


0

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

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


こんにちはクリス、答えてくれてありがとう。動的テーブルは単純に不可能なので、すでに放棄しています。XMLは冗長すぎますが、良い考えです。私の主な問題は、luceneインデックスをクエリするために静的Java関数を呼び出す必要があることです。つまり、毎回インデックスを開いたり閉じたりする必要があります。これは非常に非効率的です。JSONとXML出力を備えたRESTサービスに頼りました。
Michael-O

0

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;

実行結果:

ここに画像の説明を入力してください


-1

1つの解決策は、Luceneの出力に基づいて外部テーブルを作成することです。外部テーブル定義は簡単に変更できます(複数のファイルを指すように指定することもできます)。

だからあなたは持っているでしょう:

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

それが動作します!ファイルの定義は既知であり、外部テーブルを動的に作成できます。
オハディ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.