ヘッダーをスキップ

Oracle® Data Provider for .NET開発者ガイド
10g リリース1(10.1.0.3)
部品番号 B15519-01
  目次へ
目次
索引へ
索引

前へ 次へ  

OracleCommandオブジェクト

OracleCommandオブジェクトは、Oracleデータベース上で実行されるSQL文またはストアド・プロシージャを表します。

この項では、次の項目について説明します。

トランザクション

Oracleデータベースでは、接続のコンテキストでのみトランザクションが開始されます。いったんトランザクションが開始されると、その接続での連続するすべてのコマンドはそのトランザクションのコンテキスト内で実行されます。トランザクションはOracleConnectionオブジェクトでのみ開始でき、OracleCommandオブジェクトに対する読取り専用のTransactionプロパティは、OracleConnectionオブジェクトによって暗黙的に設定されます。したがって、アプリケーションではTransactionプロパティを設定できず、またその必要もありません。

パラメータ・バインド

ODP.NETでは、アプリケーションはデータを.NET Framework型またはODP.NET型として取得できます。

データがどちらの型で取得されるかは、アプリケーションでOUTパラメータがOracleParameterDbTypeプロパティ(.NET型)またはOracleDbTypeプロパティ(ODP.NET型)のどちらに設定されるかによって決まります。

たとえば、出力パラメータがDbType.Stringとしてバインドされている場合、出力データは.NET Stringとして返されます。逆にパラメータがOracleDbType.Charとしてバインドされている場合、出力データはOracleString型として返されます。

OracleParameterDbTypeが設定されている場合、OracleParameterOracleDbTypeはそれに応じて変更されます。またその逆も同様です。最後に設定されたパラメータが優先されます。

また、アプリケーションでは単にデータをバインドし、パラメータ値の.NET型からDbTypeOracleDbTypeの両方をODP.NETに推論させることもできます。

ODP.NETでは、次のOracleCommandメソッドの実行により、InputOutputOutputおよびReturnValueパラメータにOracleデータが移入されます。

  • ExecuteReader

  • ExecuteNonQuery

  • ExecuteScalar

アプリケーションで出力パラメータの値をバインドする必要はありません。ODP.NETにより値オブジェクトが作成され、OracleParameterValueプロパティにそのオブジェクトが移入されます。

この項では、次の項目について説明します。


関連項目:

OracleDbType列挙体

BINARY_FLOATおよびBINARY_DOUBLEデータ型

Oracle Database 10gから、BINARY_FLOATおよびBINARY_DOUBLEの2つの固有なデータ型が新たに加わりました。

BINARY_FLOATおよびBINARY_DOUBLEは、それぞれ単精度および倍精度の浮動小数点値を表します。

OracleParameterのバインドでは、BINARY_FLOATおよびBINARY_DOUBLEそれぞれに対してOracleDbType.FloatおよびOracleDbType.Doubleの列挙体を使用してください。


関連項目:


OracleDbType列挙体

OracleDbType列挙値は、OracleParameterOracleDbTypeを明示的に指定するために使用されます。

表3-2では、すべてのOracleDbType列挙値をリストし、各値について説明します。

表3-2 OracleDbType列挙値

メンバー名 説明
BFile OracleのBFILE
Blob OracleのBLOB
Byte byte
Char OracleのCHAR
Clob OracleのCLOB
Date OracleのDATE
Decimal OracleのNUMBER
Double 8バイトのFLOAT
Int16 2バイトのINTEGER
Int32 4バイトのINTEGER
Int64 8バイトのINTEGER
IntervalDS OracleのINTERVAL DAY TO SECOND
IntervalYM OracleのINTERVAL YEAR TO MONTH
Long OracleのLONG
LongRaw OracleのLONG RAW
NChar OracleのNCHAR
NClob OracleのNCLOB
NVarchar2 OracleのNVARCHAR2
Raw OracleのRAW
RefCursor OracleのREF CURSOR
Single 4バイトのFLOAT
TimeStamp OracleのTIMESTAMP
TimeStampLTZ OracleのTIMESTAMP WITH LOCAL TIME ZONE
TimeStampTZ OracleのTIMESTAMP WITH TIME ZONE
Varchar2 OracleのVARCHAR2
XmlType OracleのXMLType

DbType、OracleDbTypeおよび.NET型の推論

この項では、OracleParameterクラス内のSystem.Data.DbTypeOracleDbTypeおよびValueプロパティからの推論について説明します。

OracleParameterクラス内では、DbTypeOracleDbTypeおよびValueプロパティはリンクされています。このいずれかのプロパティの値を指定すると、1つ以上の他のプロパティの値が推論されます。

OracleDbTypeからのDbTypeの推論

OracleParameterクラス内でOracleDbTypeの値を指定すると、表3-3に示されたDbTypeの値が推論されます。

表3-3 OracleDbTypeからのSystem.Data.DbTypeの推論

OracleDbType System.Data.DbType
BFile Object
Blob Object
Byte Byte
Char StringFixedLength
Clob Object
Date Date
Decimal Decimal
Double Double
Int16 Int16
Int32 Int32
Int64 Int64
IntervalDS TimeSpan
IntervalYM Int64
Long String
LongRaw Binary
NChar StringFixedLength
NClob Object
NVarchar2 String
Raw Binary
RefCursor Object
Single Single
TimeStamp DateTime
TimeStampLTZ DateTime
TimeStampTZ DateTime
Varchar2 String
XmlType String

DbTypeからのOracleDbTypeの推論

OracleParameterクラス内でDbTypeの値を指定すると、表3-4に示されたOracleDbTypeの値が推論されます。

表3-4 DbTypeからのOracleDbTypeの推論

System.Data.DbType OracleDbType
Binary Raw
Boolean サポートなし
Byte Byte
Currency サポートなし
Date Date
DateTime TimeStamp
Decimal Decimal
Double Double
Guid サポートなし
Int16 Int16
Int32 Int32
Int64 Int64
Object サポートなし
Sbyte サポートなし
Single Single
String Varchar2
StringFixedLength Char
Time TimeStamp
UInt16 サポートなし
UInt32 サポートなし
Uint64 サポートなし
VarNumeric サポートなし

ValueからのDbTypeおよびOracleDbTypeの推論

OracleParameterクラス内で、Valueは、あらゆる.NET Frameworkデータ型またはODP.NET型にできるオブジェクト型です。OracleParameterオブジェクト内のOracleDbTypeおよびDbTypeが指定されていない場合、Valueプロパティの型からOracleDbTypeが推論されます。

表3-5に、Valueの型がいずれかの.NET Frameworkデータ型である場合に、Valueから推論されるDbTypeおよびOracleDbTypeを示します。

表3-5 Value(.NETデータ型)からのDbTypeおよびOracleDbTypeの推論

Value(.NETデータ型) System.Data.DbType OracleDbType
Byte Byte Byte
Byte[] Binary Raw
Char / Char [] String Varchar2
DateTime DateTime TimeStamp
Decimal Decimal Decimal
Double Double Double
Float Single Single
Int16 Int16 Int16
Int32 Int32 Int32
Int64 Int64 Int64
Single Single Single
String String Varchar2
TimeSpan TimeSpan IntervalDS


注意:

これ以外の.NET Frameworkデータ型からのDbTypeおよびOracleDbTypeの推論はサポートされていないため、DbTypeまたはOracleDbTypeを指定せずにOracleParameterの値としてそれ以外の.NET Frameworkデータ型を使用すると、例外が呼び出されます。

表3-6に、Valueの型がいずれかのOracle.DataAccess.Typesである場合に、Valueから推論されるDbTypeおよびOracleDbTypeを示します。

表3-6 Value(ODP.NETデータ型)からのDbTypeおよびOracleDbTypeの推論

Value(Oracle.DataAccess.Types) System.Data.DbType OracleDbType
OracleBFile Object BFile
OracleBinary Binary Raw
OracleBlob Object Blob
OracleClob Object Clob
OracleDate Date Date
OracleDecimal Decimal Decimal
OracleIntervalDS Object IntervalDS
OracleIntervalYM Int64 IntervalYM
OracleRefCursor Object RefCursor
OracleString String Varchar2
OracleTimeStamp DateTime TimeStamp
OracleTimeStampLTZ DateTime TimeStampLTZ
OracleTimeStampTZ DateTime TimeStampTZ
OracleXmlType String XmlType

PL/SQL連想配列

ODP.NETは、PL/SQL連想配列(以前はPL/SQL索引付き表と呼ばれていた)のバインドをサポートします。

アプリケーションで、OracleParameterをPL/SQLストアド・プロシージャにPL/SQL連想配列としてバインドすることができます。この機能では、次のOracleParameterプロパティを使用します。

  • CollectionType

    PL/SQL連想配列をバインドするためには、このプロパティをOracleCollectionType.PLSQLAssociativeArrayに設定する必要があります。

  • ArrayBindSize

    固定長の要素型(Int32など)ではこのプロパティは無視されます。

    可変長の要素型(Varchar2など)に対しては、ArrayBindSizeプロパティの各要素でValueプロパティの対応する要素のサイズを指定します。

    Outputパラメータ、InputOutputパラメータおよび返り値の場合、可変長の変数に対してこのパラメータを設定する必要があります。

  • ArrayBindStatus

    このプロパティでOracleParameter.Valueプロパティの各要素の実行ステータスを指定します。

  • Size

    このプロパティで、PL/SQL連想配列にバインドする要素の最大数を指定します。

  • Value

    このプロパティには値の配列を設定するか、nullまたはDBNull.Valueを設定します。

コード例

この例は、3つのOracleParameterオブジェクトをPL/SQL連想配列としてバインドしています。具体的には、Param1Inパラメータとして、Param2InputOutputパラメータとして、Param3Outputパラメータとしてバインドします。

PL/SQLパッケージ: MYPACK

/* Setup the tables and required PL/SQL:

   CREATE TABLE T1(COL1 number, COL2 varchar2(20));

   CREATE or replace PACKAGE MYPACK AS
     TYPE AssocArrayVarchar2_t is table of VARCHAR(20) index by BINARY_INTEGER;
     PROCEDURE TestVarchar2(
       Param1 IN     AssocArrayVarchar2_t,
       Param2 IN OUT AssocArrayVarchar2_t,
       Param3    OUT AssocArrayVarchar2_t);
     END MYPACK;

   CREATE or REPLACE package body MYPACK as
     PROCEDURE TestVarchar2(
       Param1 IN     AssocArrayVarchar2_t,
       Param2 IN OUT AssocArrayVarchar2_t,
       Param3    OUT AssocArrayVarchar2_t)
     IS
     i integer;
     BEGIN
       -- copy a few elements from Param2 to Param1\n
       Param3(1) := Param2(1);
       Param3(2) := NULL;
       Param3(3) := Param2(3);
       -- copy all elements from Param1 to Param2\n
       Param2(1) := Param1(1);
       Param2(2) := Param1(2);
       Param2(3) := Param1(3);
       -- insert some values to db\n
       FOR i IN 1..3 LOOP
         insert into T1 values(i,Param2(i));
       END LOOP;
     END TestVarchar2;
   END MYPACK;
 */

// C#

using System;
using System.Data;
using Oracle.DataAccess.Client;

class AssociativeArraySample
{
  static void Main()
  {
    OracleConnection con = new OracleConnection();

    con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle";
    con.Open();
    Console.WriteLine("Connected to Oracle" + con.ServerVersion);

    OracleCommand cmd = new OracleCommand(
      "begin MyPack.TestVarchar2(:1, :2, :3); end;", con);

    OracleParameter Param1 = cmd.Parameters.Add("1", OracleDbType.Varchar2);
    OracleParameter Param2 = cmd.Parameters.Add("2", OracleDbType.Varchar2);
    OracleParameter Param3 = cmd.Parameters.Add("3", OracleDbType.Varchar2);

    Param1.Direction = ParameterDirection.Input;
    Param2.Direction = ParameterDirection.InputOutput;
    Param3.Direction = ParameterDirection.Output;

    // Specify that we are binding PL/SQL Associative Array
    Param1.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
    Param2.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
    Param3.CollectionType = OracleCollectionType.PLSQLAssociativeArray;

    // Setup the values for PL/SQL Associative Array
    Param1.Value = new string[3] {
      "First Element", "Second Element ", "Third Element "
    };
    Param2.Value = new string[3] {
      "First Element", "Second Element ", "Third Element "
    };
    Param3.Value = null;

    // Specify the maximum number of elements in the PL/SQL Associative Array
    Param1.Size = 3;
    Param2.Size = 3;
    Param3.Size = 3;

    // Setup the ArrayBindSize for Param1
    Param1.ArrayBindSize = new int[3] { 13, 14, 13 };

    // Setup the ArrayBindStatus for Param1
    Param1.ArrayBindStatus = new OracleParameterStatus[3] {
      OracleParameterStatus.Success, OracleParameterStatus.Success,
      OracleParameterStatus.Success};

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

    // Setup the ArrayBindSize for Param3
    Param3.ArrayBindSize = new int[3] { 20, 20, 20 };

    // execute the cmd
    cmd.ExecuteNonQuery();

    //print out the parameter's values
    Console.WriteLine("parameter values after executing the PL/SQL block");
    for (int i = 0; i < 3; i++)
      Console.WriteLine("Param2[{0}] = {1} ", i,
        (cmd.Parameters[1].Value as Array).GetValue(i));

    for (int i = 0; i < 3; i++)
      Console.WriteLine("Param3[{0}] = {1} ", i,
        (cmd.Parameters[2].Value as Array).GetValue(i));

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

配列バインド

配列バインド機能により、アプリケーションはOracleParameterクラスを使用して型の配列をバインドできます。配列バインド機能を使用すると、アプリケーションは1回のデータベース・ラウンドトリップで複数の行を表に挿入できます。

次のコード例では、1回のデータベース・ラウンドトリップで3つの行をDept表に挿入します。OracleCommandArrayBindCountプロパティにより、文の実行時に使用される配列の要素数が定義されます。

// C#

using System;
using System.Data;
using Oracle.DataAccess.Client;

class ArrayBindSample
{
  static void Main()
  {
    OracleConnection con = new OracleConnection();
    con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle;";
    con.Open();
    Console.WriteLine("Connected successfully");

    int[] myArrayDeptNo = new int[3] { 10, 20, 30 };
    OracleCommand cmd = new OracleCommand();

    // Set the command text on an OracleCommand object
    cmd.CommandText = "insert into dept(deptno) values (:deptno)";
    cmd.Connection = con;

    // Set the ArrayBindCount to indicate the number of values
    cmd.ArrayBindCount = 3;

    // Create a parameter for the array operations
    OracleParameter prm = new OracleParameter("deptno", OracleDbType.Int32);

    prm.Direction = ParameterDirection.Input;
    prm.Value = myArrayDeptNo;

    // Add the parameter to the parameter collection
    cmd.Parameters.Add(prm);

    // Execute the command
    cmd.ExecuteNonQuery();
    Console.WriteLine("Insert Completed Successfully");

    // Close and Dispose OracleConnection object
    con.Close();
    con.Dispose();
  }
}


関連項目:

詳細は、「Value」を参照してください。

OracleParameter配列バインド・プロパティ

OracleParameterオブジェクトでは、配列バインド機能を使用する際の粒度の制御のために2つのプロパティが提供されます。

  • ArrayBindSizeプロパティ

    ArrayBindSizeプロパティは、配列内の対応する値ごとの最大サイズを指定する整数の配列です。ArrayBindSizeプロパティが配列内の値ごとのサイズを指定するという点以外は、ArrayBindSizeプロパティとOracleParameterSizeプロパティは同じです。

    実行前に、アプリケーションによってArrayBindSizeにデータが移入される必要があります。実行後は、ODP.NETによってArrayBindSizeにデータが移入されます。

    ArrayBindSizeは、ClobBlobおよびVarchar2などの可変長を持つパラメータの型にのみ使用されます。サイズは、バイナリ・データ型の場合はバイトで、Unicode文字列型の場合は文字で表されます。文字列型の場合、末尾の文字はカウントされません。サイズは、明示的に設定されていない場合は実際の値のサイズから推論されます。出力パラメータの場合、各値のサイズはODP.NETにより設定されます。固定長のデータ型の場合、ArrayBindSizeプロパティは無視されます。

  • ArrayBindStatusプロパティ

    ArrayBindStatusプロパティは、パラメータに対する配列内の対応する値ごとのステータスを指定するOracleParameterStatus値の配列です。ArrayBindStatusプロパティは、配列内の値ごとのステータスを指定するという点以外は、OracleParameterStatusプロパティと同じです。

    実行前に、アプリケーションによってArrayBindStatusプロパティにデータが移入される必要があります。実行後には、ODP.NETによってこのプロパティにデータが移入されます。実行前に、ArrayBindStatusを使用するアプリケーションでは、パラメータに対する配列内の対応する要素にnull値を指定できます。実行後、ODP.NETによってArrayBindStatus配列にデータが移入され、配列内の対応する要素がnull値を持つか、値がフェッチされたときにデータの切捨てが行われたかが示されます。

配列バインドのエラー処理

配列バインドの実行中にエラーが発生した場合、Valueプロパティ内のどの要素がエラーの原因かを判断することは困難です。ODP.NETにはエラーが発生した行を特定する機能があるため、エラーを引き起こした要素をその行の中から簡単に見つけることができます。

配列バインドの実行中にOracleExceptionがスローされると、OracleErrorCollectionに1つ以上のOracleErrorオブジェクトが追加されます。1つ1つのOracleErrorオブジェクトは実行中に発生した個々のエラーを表し、プロバイダ固有のプロパティであるArrayBindIndexが含まれます。ArrayBindIndexにはエラーが発生した行番号が示されます。

/* Database Setup
drop table depttest;
create table depttest(deptno number(2));
*/

// C#

using System;
using System.Data;
using Oracle.DataAccess.Client;

class ArrayBindExceptionSample
{
  static void Main()
  {
    OracleConnection con = new OracleConnection();
    con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle;";
    con.Open();

    OracleCommand cmd = new OracleCommand();

    // Start a transaction
    OracleTransaction txn = con.BeginTransaction(IsolationLevel.ReadCommitted);

    try
    {
      int[] myArrayDeptNo = new int[3] { 10, 200000, 30 };
      // int[] myArrayDeptNo = new int[3]{ 10,20,30};

      // Set the command text on an OracleCommand object
      cmd.CommandText = "insert into depttest(deptno) values (:deptno)";
      cmd.Connection = con;

      // Set the ArrayBindCount to indicate the number of values
      cmd.ArrayBindCount = 3;

      // Create a parameter for the array operations
      OracleParameter prm = new OracleParameter("deptno", OracleDbType.Int32);

      prm.Direction = ParameterDirection.Input;
      prm.Value = myArrayDeptNo;

      // Add the parameter to the parameter collection
      cmd.Parameters.Add(prm);

      // Execute the command
      cmd.ExecuteNonQuery();
    }
    catch (OracleException e)
    {
      Console.WriteLine("OracleException {0} occured", e.Message);
      if (e.Number == 24381)
        for (int i = 0; i < e.Errors.Count; i++)
          Console.WriteLine("Array Bind Error {0} occured at Row Number {1}",
            e.Errors[i].Message, e.Errors[i].ArrayBindIndex);

      txn.Commit();
    }
    cmd.Parameters.Clear();
    cmd.CommandText = "select count(*) from depttest";

    decimal rows = (decimal)cmd.ExecuteScalar();

    Console.WriteLine("{0} row have been inserted", rows);
    con.Close();
    con.Dispose();
  }
}

関連項目:

詳細は、「ArrayBindIndex」を参照してください。

OracleParameterStatus列挙型

表3-7に、OracleParameterStatus列挙体の様々な値を示します。

表3-7 OracleParameterStatusのメンバー

メンバー名 説明
Success 入力パラメータの場合、入力値が列に割り当てられたことを示します。

出力パラメータの場合、プロバイダにより完全な値がパラメータに割り当てられたことを示します。

NullFetched null値が列またはOUTパラメータからフェッチされたことを示します。
NullInsert null値が列に挿入されることを示します。
Truncation 列からデータをフェッチする際に切捨てが発生したことを示します。

文キャッシング

文キャッシングにより、最初の実行で作成されたサーバー・カーソルのキャッシングによる実行の前に、各SQL文またはPL/SQL文を解析する必要がなくなります。同じ文を(場合によっては異なるパラメータ値を使用して)後で実行する場合、カーソルから解析された情報を再利用して、文を解析せずに実行することで、パフォーマンスが向上します。

文キャッシングによるパフォーマンスを向上させるために、繰り返し実行される文のみをキャッシュすることをお薦めします。さらに、SQL文またはPL/SQL文は、リテラル値ではなくパラメータを使用する必要があります。これは、文キャッシングが有効な場合、作成済のパラメータ化された文は、異なるパラメータ値を使用して同じ文を後で実行するときに再利用できるためです。

Statement Caching 文キャッシングの接続文字列属性

次の接続文字列属性は、ODP.NET文キャッシング機能の動作を制御します。

  • Statement Cache Size

    この属性は、ODP.NET文キャッシングを有効化または無効化します。デフォルトでは、この属性は0に設定され、ODP.NET文キャッシングは無効です。0より大きい値に設定した場合、ODP.NET文キャッシングが有効になり、指定された値は、接続用にキャッシュできる文の最大数として使用されます。指定された最大キャッシュ・サイズまで接続がキャッシュされると、最低使用頻度のカーソルが解放され、新しく作成されたカーソルをキャッシュするためのスペースが確保されます。

  • Statement Cache Purge

    この属性は、接続がクローズされた場合、または接続プールに戻された場合にキャッシュされるすべての文を消去する方法を提供します。デフォルトでは、この属性はFalseに設定されています。つまり、接続がプールに戻されてもカーソルは解放されません。

文キャッシングのメソッドおよびプロパティ

次のメソッドおよびプロパティは、文キャッシングが有効な場合のみ当てはまります。

  • OracleCommand.AddToStatementCacheプロパティ

    文キャッシングが有効な場合、このプロパティをTrueに設定すると、文の実行時にキャッシュに文が追加されます。文キャッシングが無効な場合、またはこのプロパティがFalseに設定されている場合、実行された文はキャッシュされません。デフォルトでは、このプロパティはTrueに設定されています。

  • OracleConnection.PurgeStatementCacheメソッド

    このメソッドは、特定の接続に関連付けられたサーバーでオープンしているカーソルをすべてクローズすることで、キャッシュされた文をすべて消去します。このコールの後も、文キャッシングは有効です。

接続と文キャッシング

文キャッシングは、接続ごとに個別に管理されます。このため、異なる接続で同じ文を実行するには、接続ごとに1回消去して、接続ごとに個別のカーソルをキャッシュする必要があります。

プーリングと文キャッシング

プーリングと文キャッシングは同時に使用できます。接続プーリングが有効で、Statement Change PurgeFalseに設定されている場合、個別の接続で実行される文は、プールされた接続の存続中にキャッシュされます。Statement Cache PurgeTrueに設定されている場合、接続がプールに戻されたときに、キャッシュされたすべてのカーソルが解放されます。接続プーリングが無効な場合、カーソルは接続の存続中にキャッシュされますが、OracleConnectionオブジェクトがクローズまたは処理されたときにカーソルもクローズされます。