2

次の問題があります。私は経験豊富なJavaプログラマーですが、SQLおよびPL/SQLでは少しn00bです。

私は次のことをする必要があります。

1いくつかの配列と他のいくつかの変数をプロシージャに渡します

2配列の値をループし(すべて同じ数の項目があります)、SQLステートメントを動的に作成します

3このステートメントを実行し、結果セット(プロシージャーのOUTパラメーター)に追加します。

SQLクエリをその場で作成し、実行して結果を結果セット(REF CURSOR)に追加した経験はすでにありますが、ループして各呼び出しの結果をに追加する方法がわかりません。同じ結果セットにクエリを実行します。これが可能かどうかさえわかりません。

これが私がこれまでに持っているものです(簡単にするためにコードを編集しました)。RESULT_SETの内容を最新のクエリ結果に置き換えているだけなので、間違っていることがわかります(これは、このプロシージャを呼び出しているJavaで確認されています)。

ありとあらゆる助けをいただければ幸いです。

TYPE REF_CURSOR IS REF CURSOR;  




PROCEDURE GET_DATA_FASTER(in_seq_numbers IN seq_numbers_array, in_values IN text_array, in_items IN text_array, list IN VARCHAR2, RESULT_SET OUT REF_CURSOR) AS  
  query_str VARCHAR2(4000);

  seq_number NUMBER;
  the_value VARCHAR2(10);
  the_item VARCHAR2(10);

  BEGIN

    FOR i IN 1..in_seq_numbers.COUNT
    LOOP

      seq_number := in_seq_numbers(i);
      the_value := trim(in_values(i));
      the_item := trim(in_items(i));

      query_str := 'SELECT distinct '||seq_number||' as seq, value, item
      FROM my_table ai';                    

      query_str := query_str || '
      WHERE ai.value = '''||the_value||''' AND ai.item = '''||the_item||'''
      AND ai.param = ''BOOK''
      AND ai.prod in (' || list || ');

      OPEN RESULT_SET FOR query_str;

    END LOOP;

    EXCEPTION WHEN OTHERS THEN
      RAISE;

  END GET_DATA_FASTER;
4

1 に答える 1

4

パイプライン化されたテーブル関数は、特にデータを取得するだけの場合は、必要なものに適しているようです。http://www.oracle-base.com/articles/misc/pipelined-table-functions.phpを参照してください

あなたがすることはあなたの出力行のためのタイプを作成することです。したがって、あなたの場合、次のようなオブジェクトを作成します

CREATE TYPE get_data_faster_row AS OBJECT(
    seq    NUMBER(15,2),
    value  VARCHAR2(10),
    item   VARCHAR2(10)
);

次に、上記の行タイプで構成されるテーブルであるテーブルタイプを作成します

CREATE TYPE get_data_faster_data IS TABLE OF get_data_faster_row;

次に、パイプライン方式でデータを返すテーブル関数を作成します。Oracleでのパイプライン化は、.netでのyield returnに少し似ています(これに精通しているかどうかはわかりません)。必要なすべての行を見つけて、ループ内で一度に1つずつ「パイプ」します。関数が完了すると、返されるテーブルは、パイプアウトしたすべての行で構成されます。

CREATE FUNCTION Get_Data_Faster(params) RETURN get_data_faster_data PIPELINED AS
BEGIN
    -- Iterate through your parameters 
        --Iterate through the results of the select using
        -- the current parameters. You'll probably need a 
        -- cursor for this
        PIPE ROW(get_data_faster_row(seq, value, item));
        LOOP;
    LOOP;
END;

編集:以下のアレックスのコメントに続いて、あなたはこのようなものが必要です。私はこれをテストすることができませんでしたが、それはあなたが始めることができるはずです:

CREATE FUNCTION Get_Data_Faster(in_seq_numbers IN seq_numbers_array, in_values IN text_array, in_items IN text_array, list IN VARCHAR2) RETURN get_data_faster_data PIPELINED AS
    TYPE r_cursor IS REF CURSOR;
    query_results r_cursor;
    results_out get_data_faster_row := get_data_faster_row(NULL, NULL, NULL);

    query_str VARCHAR2(4000);

    seq_number NUMBER;
    the_value VARCHAR2(10);
    the_item VARCHAR2(10);

BEGIN
    FOR i IN 1..in_seq_number.COUNT
    LOOP
        seq_number := in_seq_numbers(i);
        the_value := trim(in_values(i));
        the_item := trim(in_items(i));

        query_str := 'SELECT distinct '||seq_number||' as seq, value, item
        FROM my_table ai';                    

        query_str := query_str || '
        WHERE ai.value = '''||the_value||''' AND ai.item = '''||the_item||'''
        AND ai.param = ''BOOK''
        AND ai.prod in (' || list || ');

        OPEN query_results FOR query_str;

        LOOP
            FETCH query_results INTO 
                results_out.seq,
                results_out.value,
                results_out.item;
            EXIT WHEN query_results%NOTFOUND;
            PIPE ROW(results_out);
        END LOOP;

    CLOSE query_results;

    END LOOP;

END;

以下のアレックスのコメントからの追加情報は、答えに役立ちます:

異なるソースからの複数のループを持つことができ、それぞれからのデータが同じオブジェクトタイプに入れられている限り、関数内の任意の場所でパイプ行ステートメントを使用してそれらをポンプアウトし続けることができます。呼び出し元は、それらをパイプした順序で行を持つテーブルとして表示します。プロシージャを呼び出して結果セットを出力パラメータとして取得するのではなく、select seq、value、item from table(package.get_data_faster(a、b、c、d))としてクエリを実行できます。もちろん、パイプされる順序が希望どおりでない場合は、句ごとに並べ替えます。

于 2012-09-26T15:25:11.120 に答える