16

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 機能と互換性がある必要があります。

ありがとう、ロバート

4

7 に答える 7

28

要素自体に文字列が含まれていないことが 100% 確実であると仮定すると、CSV を使用するのがおそらく最も簡単な方法です。

これを行う代替の、おそらくより堅牢な方法は、文字列のテーブルとしてカスタム型を作成することです。文字列が 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()関数は、カスタム型を単一の列「COLUMN_VALUE」を持つテーブルに変換し、他のテーブルと同様に扱うことができます (結合またはこの場合は副選択も同様です)。

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

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

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

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

于 2008-10-28T11:52:53.707 に答える
1

可変数のパラメーターを持つプロシージャーを直接作成する方法はないと思います。ただし、ここで説明されている、問題に対する少なくとも部分的な解決策がいくつかあります。

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

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

于 2008-10-28T11:42:54.477 に答える
1

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

Mark A. Williams による素晴らしい記事

于 2009-12-11T15:19:18.660 に答える
0

長いパラメーター リストを使用して値をテーブル コンストラクターにロードしないのはなぜですか? このトリックの 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);
于 2009-08-05T16:11:53.673 に答える
-1

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

アスクトムを見る

于 2008-10-28T11:26:34.137 に答える
-1

私は 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)) 
于 2008-10-28T10:22:55.513 に答える
-3

なぜストアドプロシージャでなければならないのですか?準備されたステートメントをプログラムで作成できます。

于 2008-10-28T10:26:39.077 に答える