3

OracleParameter への配列バインディングを使用して、Oracle SQL クエリのパフォーマンスを向上させようとしています。

これは基本的に私がやろうとしていることです:

                List<string> IDValList = new List<string>();
                IDValList.Add( "IDOne" );
                IDValList.Add( "IDTwo" );

                List<int> sizes = new List<int>();
                foreach( string id in IDValList )
                {
                    sizes.Add( id.Length );
                }

                using( OracleCommand cmd = new OracleCommand( "select col1, col2, col3 from table where col4 in ( :idArray )", _conn ) )
                {
                    cmd.CommandType = System.Data.CommandType.Text;

                    OracleParameter arrayParam = new OracleParameter( "idArray", OracleDbType.Varchar2 );
                    arrayParam.Direction = System.Data.ParameterDirection.Input;
                    arrayParam.Value = IDValList.ToArray();
                    arrayParam.ArrayBindSize = sizes.ToArray();

                    cmd.ArrayBindCount = IDValList.Count;
                    cmd.Parameters.Add( arrayParam );

                    using( OracleDataReader dr = cmd.ExecuteReader() )
                    {
                        while( dr.Read() )
                        {
                           // now read the row...

これはコンパイルして実行しますが、最初の ID に対して常に 1 行しか返されません。パラメータの配列の残りの値を無視するようなものです。

興味深いことに、パラメーターの ArrayBindStatus はすべての値に対して成功しています。

私は何が欠けていますか?それとも、これは OracleReader では機能しませんか?

ありがとう

編集: 基本的に、私はこの例に従おうとしていますが、DataReader を使用してクエリから結果のデータセットを読み取れるようにしたいと考えています。

http://www.oracle.com/technology/oramag/oracle/09-sep/o59odpnet.html

4

2 に答える 2

1

検索している「リスト内の変数」を実行するには、いくつかの方法があります。バインドされたパラメータを利用します。

これはこれに基づいています:http://asktom.oracle.com/pls/asktom/f?p = 100:11:0 :::: P11_QUESTION_ID: 210612357425

率直に言って、パフォーマンスの向上だけでなく、セキュリティのレベルを上げるためにも、バインド変数をできるだけ頻繁に使用するようにしています。

猫の皮を剥ぐ方法はたくさんありますが、これは(冗長な間)それを行うべきです

Oracleの場合-タイプを作成します。タイプvarcharTableTypeをvarchar2(255)のテーブルとして作成または置換します。

--create your function
function in_varchar( p_string in varchar2 ) return varcharTableType  
    as
        l_string        long default p_string || ',';
        l_data          varcharTableType := varcharTableType();
        n               number;
    begin
      loop
          exit when l_string is null;
          n := instr( l_string, ',' );
         l_data.extend;
         l_data(l_data.count) := 
                 ltrim( rtrim( substr( l_string, 1, n-1 ) ) );
         l_string := substr( l_string, n+1 );
    end loop;

    RETURN L_DATA;
  END in_varchar;

.netでクエリを修正します

 col4 in ( select COLUMN_VALUE from table(in_varchar(:idArray )) )

(ところで、このコードのほとんどは、オラクルフォーラムで回答した以前の投稿からコピーしました:http://forums.oracle.com/forums/thread.jspa?messageID = 4299793&# 4299793

これにより実際に作成されるため、配列バインディングを使用する必要はありません。コンマで区切られた文字列であることを確認してください。:idArray = "A、B、C"

もう1つのオプションは、selectステートメントをrefカーソル配列に戻すことです。

        /* example table
         * 
Create  Table Zzztab(Deptno Number, Deptname Varchar2(50) , Loc Varchar2(50) , State Varchar2(2) , Idno Number(10)) ;
/
insert into Zzztab(Deptno , Deptname  , Loc  , State , Idno)
values (0,'Zero','US','NY',0);
insert into Zzztab(Deptno , Deptname  , Loc  , State , Idno)
values (1,'One','CA','ON',1);
insert into Zzztab(Deptno , Deptname  , Loc  , State , Idno)
values (2,'Three','IS',null,2);
insert into Zzztab(Deptno , Deptname  , Loc  , State , Idno)
values (3,'Four','BD',null,3);
         */
    string connectStr = GetConnectionString();

    // Initialize array of data
    String[] myArrayDeptName = { "Zero", "Three", "Four" };

    OracleConnection connection = new OracleConnection(connectStr);
    OracleCommand command = new OracleCommand();
    command.Connection = connection;
    command.CommandType = CommandType.Text ;
    command.CommandText = "begin open :cur for SELECT DEPTNO, DEPTNAME FROM ZZZTAB WHERE DEPTNAME = :DEPT; end;";

    command.ArrayBindCount = myArrayDeptName.Length ;
    command.BindByName = true;

    OracleParameter cur = new OracleParameter("cur", OracleDbType.RefCursor );
    cur.Direction = ParameterDirection.Output;
    cur.Value = myArrayDeptName;
    command.Parameters.Add(cur);

    // deptname parameter
    OracleParameter deptNameParam = new OracleParameter("DEPT", OracleDbType.Varchar2);
    deptNameParam.Direction = ParameterDirection.Input;
    deptNameParam.Value = myArrayDeptName;
    command.Parameters.Add(deptNameParam);

     try
    {
        connection.Open();
        command.ExecuteNonQuery();

        foreach (Oracle.DataAccess.Types.OracleRefCursor  rc in (Oracle.DataAccess.Types.OracleRefCursor[])cur.Value)
        { ...  fill in an join the datatables

まったく同じロジックを使用して、列をそれぞれの配列に戻すことができます。

于 2010-08-06T11:49:54.293 に答える
-3

それは動作します:

  using
  ( OracleCommand cmd = 
    new OracleCommand("select col1, col2, col3 from table where col4 in (" + string.Join(",", IDValList) + ")", _conn ) )

リストから最初の要素を渡すだけだからです。

于 2010-08-06T11:18:54.350 に答える