2012-03-14 57 views
4

件名にはconfusingdocsという多数の質問がありますが、これまでのところ運がありません。ODP.NET文字列の配列をOracleのストアドプロシージャに渡す方法は?

次のPL/SQLストアド・プロシージャがあります。タイプListcarは、以下である

PROCEDURE PS_test(
    Liste1 Listcar, 
    Liste2 Listcar, 
    P_CURS_MESSAGE out CURSOR_REF_TYP 
) 

TYPEのListcarがVARCHAR2のVARRAY(100)(50)です。値の割り当てで、次のエラーで

string[] list = { "name1", "name1" }; 

OracleParameter oParam = (OracleParameter)myOracleCommand.CreateParameter(); 
oParam.ParameterName = "Liste1"; 
oParam.UdtTypeName = "LISTCAR"; 
oParam.Value = list; 
oParam.Direction = ParameterDirection.Input; 
myOracleCommand.Parameters.Add(oParam); 

:ここ

は、私がこれまでにしようとしているものです

ArrayBindSizeによりを設定するには、型varchr2を使用しようとした
Value does not fall within the expected range. 

ので、しかし、これまで運がなかった。

インターフェイスIOracleArrayTypeFactoryはどこかで役割を果たすかもしれませんが、どうでしょうか?

+0

パフォーマンスを向上させるため、関連配列はVARRAYよりも優先されます。関連する配列を含むパフォーマンス関連のウォークスルーがいくつかあります。http://www.oracle.com/webfolder/technetwork/tutorials/obe/db/dotnet/OptimizePerfODPNET/OptimizePerfODPNET.htmまた、VARRAYはユーザー定義型なので、これらを使用すると、一般的な.NETのUDTを使用する方法がわかります。http://www.oracle.com/webfolder/technetwork/tutorials/obe/db/dotnet/userdefinedtypes/userDefinedTypes.htm –

答えて

9

私はODP.NETでudtType機能を使用していないので、これでどのように目標を達成するかはわかりません。しかし、文字列の配列を渡すには、それを必要としません。

添付したドキュメントのように、ストアドプロシージャを含むパッケージを作成し、入力パラメータとして連想配列(VARRAYではなく)を使用する必要があります。例えば

:今

-- Create the table 
CREATE TABLE TBLTEST (testID NUMBER, name VARCHAR2(50)); 

CREATE SEQUENCE seq_test 
    MINVALUE 1 
    START WITH 1 
    INCREMENT BY 1 
    NOCACHE; 

CREATE OR REPLACE PACKAGE pkgTestArrayBinding 
AS 
    -- Define an local scope associative array type called T_ASSOCIATIVE_ARRAY and make it as the type of input parameter 
    TYPE T_ASSOCIATIVE_ARRAY IS TABLE OF VARCHAR(50) INDEX BY PLS_INTEGER; 
    PROCEDURE TestArrayBinding(
     Param1 IN T_ASSOCIATIVE_ARRAY, 
     Param2 IN T_ASSOCIATIVE_ARRAY); 
END pkgTestArrayBinding; 
/

CREATE OR REPLACE PACKAGE BODY pkgTestArrayBinding 
AS 
    PROCEDURE TestArrayBinding(
     Param1 IN T_ASSOCIATIVE_ARRAY, 
     Param2 IN T_ASSOCIATIVE_ARRAY) 
    AS 
    BEGIN 
     -- for all loop to insert them in a batch 
     FORALL indx IN 1..Param1.COUNT 
      INSERT INTO tblTest VALUES(seq_test.nextval, Param1(indx)); 

     FORALL indx IN 1..Param2.COUNT 
      INSERT INTO tblTest VALUES(seq_test.nextval, Param2(indx)); 
    END TestArrayBinding; 
END pkgTestArrayBinding; 
/

、このコードを実行し、独自の接続文字列を置きます。

namespace Con1 
{ 
    using System; 
    using System.Data; 

    using Oracle.DataAccess.Client; 

    /// <summary> 
    /// The program. 
    /// </summary> 
    internal class Program 
    { 
     #region Methods 

     /// <summary> 
     /// The main. 
     /// </summary> 
     private static void Main() 
     { 
      var con = new OracleConnection { ConnectionString = "User Id=usr;Password=pass;Data Source=XE" }; 

      con.Open(); 
      Console.WriteLine("Connected to Oracle" + con.ServerVersion); 

      // create command to run your package 
      var cmd = new OracleCommand("BEGIN pkgTestArrayBinding.TestArrayBinding(:Param1, :Param2); END;", con); 

      var param1 = cmd.Parameters.Add("Param1", OracleDbType.Varchar2); 
      var param2 = cmd.Parameters.Add("Param2", OracleDbType.Varchar2); 

      param1.Direction = ParameterDirection.Input; 
      param2.Direction = ParameterDirection.Input; 

      // Specify that we are binding PL/SQL Associative Array 
      param1.CollectionType = OracleCollectionType.PLSQLAssociativeArray; 
      param2.CollectionType = OracleCollectionType.PLSQLAssociativeArray; 

      // Setup the values for PL/SQL Associative Array 
      param1.Value = new[] { "First Element", "Second Element ", "Third Element_" }; 
      param2.Value = new[] { "Fourth Element", "Fifth Element ", "Sixth Element " }; 

      // Specify the maximum number of elements in the PL/SQL Associative Array 
      // this should be your array size of your parameter Value. 
      param1.Size = 3; 
      param2.Size = 3; 

      // Setup the ArrayBindSize for each elment in the array, 
      // it should be bigger than the original length of element to avoid truncation 
      param1.ArrayBindSize = new[] { 13, 14, 13 }; 

      // Setup the ArrayBindSize for Param2 
      param2.ArrayBindSize = new[] { 20, 20, 20 }; 

      // execute the cmd 
      cmd.ExecuteNonQuery(); 

      // I am lazy to query the database table here, but you should get you data now. 
      // watch what happened to element "Third Element_" 

      // Close and Dispose OracleConnection object 
      con.Close(); 
      con.Dispose(); 
      Console.WriteLine("Disconnected"); 
     } 

     #endregion 
    } 
} 
+0

ユーザー定義の型を使用します。それに対処する時間がない、我々は良い古いに落ちる|パフォーマンスのために長い間); o) – Vinzz

+0

私は同意します。配列を渡す必要があるストアドプロシージャごとにパッケージを作成する必要があります...私たちはそれを嫌いです...しかし、パフォーマンスのメリットは得られます。 :) – Yin

+0

OracleParameterのSizeプロパティは、配列のサイズではなく、列内のデータの最大サイズをバイト単位で指定します。 –

関連する問題