質問

IN句の入力に使用される可変数のパラメーター値を受け入れるOracleストアドプロシージャを作成するにはどうすればよいですか?

これは私が達成しようとしていることです。更新する行の主キーの変数リストを渡すためにPLSQLで宣言する方法がわかりません。

FUNCTION EXECUTE_UPDATE
  ( <parameter_list>
   value IN int)
  RETURN  int IS
BEGIN 
    [...other statements...]
    update table1 set col1 = col1 - value where id in (<parameter_list>) 

    RETURN SQL%ROWCOUNT ;
END;

また、このプロシージャをC#から呼び出したいので、.NET機能と互換性がある必要があります。

ありがとう、 ロバート

役に立ちましたか?

解決

CSVを使用するのがおそらく最も簡単な方法です。要素に文字列が含まれないことを100%確信できる場合は、

これを行うための、おそらくより堅牢な代替方法は、文字列のテーブルとしてカスタムタイプを作成することです。あなたの文字列が100文字より長くなることはないと仮定すると、次のようになります:

CREATE TYPE string_table AS TABLE OF varchar2(100);

このタイプの変数をストアドプロシージャに渡し、直接参照できます。あなたの場合、次のようなものです:

FUNCTION EXECUTE_UPDATE(
    identifierList string_table,
    value int)
RETURN int
IS
BEGIN

    [...other stuff...]

    update table1 set col1 = col1 - value 
    where id in (select column_value from table(identifierList));

    RETURN SQL%ROWCOUNT;

END

table()関数は、カスタムタイプを単一の列&quot; COLUMN_VALUE&quot;を持つテーブルに変換します。これにより、他のテーブルと同様に処理できます(結合、またはこの場合、サブセレクト)。

この利点は、Oracleがコンストラクタを作成することです。そのため、ストアドプロシージャを呼び出すときは、次のように記述できます。

execute_update(string_table('foo','bar','baz'), 32);

このコマンドをC#からプログラムで作成できると想定しています。

余談ですが、私の会社では、文字列、倍精度、整数などのリストの標準として定義されたこれらのカスタムタイプがいくつかあります。また、 Oracle JPublisher を使用して、これらのタイプから対応するJavaオブジェクトに直接マップします。ざっと見て回ったのですが、C#に直接相当するものが見つかりませんでした。 Java開発者がこの質問に出くわした場合に備えて言及すると思いました。

他のヒント

Mark A. Williamsによる次の記事を見つけました。この記事は、このスレッドに役立つと思います。この記事は、連想配列(TYPE myType IS TABLE OF mytable.row%TYPE INDEX BY PLS_INTEGER)を使用して、C#からPL / SQLプロシージャに配列を渡す良い例を示しています。

マークA.ウィリアムズのすばらしい記事

可変数のパラメータを持つプロシージャを直接作成する方法はないと思います。 ただし、こちら

  1. 典型的な呼び出しタイプがある場合、プロシージャのオーバーロードが役立つ場合があります。
  2. パラメーターの数に上限がある場合(およびそのタイプも事前にわかっている場合)、パラメーターのデフォルト値が役立つ場合があります。
  3. 最適なオプションは、データベースカーソルへのポインターであるカーソル変数の使用です。

残念ながら、.NET環境の経験はありません。

長いパラメーターリストを使用して、値をテーブルコンストラクターに読み込むだけではどうですか?これがこのトリックのSQL / PSMです

UPDATE Foobar
   SET x = 42
 WHERE Foobar.keycol
      IN (SELECT X.parm
            FROM (VALUES (in_p01), (in_p02), .., (in_p99)) X(parm)
           WHERE X.parm IS NOT NULL);

なぜストアドプロシージャである必要があるのですか?プログラムで準備済みステートメントを作成できます。

Oracleでこれを行ったことはありませんが、SQL Serverでは、関数を使用してCSV文字列をテーブルに変換し、IN句で使用できます。これをOracle用に書き直すのは簡単です(私は思う!)

CREATE Function dbo.CsvToInt ( @Array varchar(1000)) 
returns @IntTable table 
    (IntValue nvarchar(100))
AS
begin

    declare @separator char(1)
    set @separator = ','

    declare @separator_position int 
    declare @array_value varchar(1000) 

    set @array = @array + ','

    while patindex('%,%' , @array) <> 0 
    begin

      select @separator_position =  patindex('%,%' , @array)
      select @array_value = left(@array, @separator_position - 1)

        Insert @IntTable
        Values (Cast(@array_value as nvarchar))

      select @array = stuff(@array, 1, @separator_position, '')
    end

    return
end

その後、CSV文字列(例: '0001,0002,0003')を渡して、次のような操作を実行できます

UPDATE table1 SET 
       col1 = col1 - value 
WHERE id in (SELECT * FROM csvToInt(@myParam)) 

AskTom Webサイトには、CSV文字列を解析する関数を作成し、これをSQL Serverの例と同様の方法でステートメントで使用する方法を示す記事があります。

質問

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top