- PR -

エラーORA-01000: 最大オープン・カーソル数を超えました

1
投稿者投稿内容
コウイチ
常連さん
会議室デビュー日: 2003/11/04
投稿数: 48
投稿日時: 2005-09-30 10:49
ファイルからデータを取得して、OracleへINSERTするアプリを作成しています。
実行すると以下のエラーがでてしまいます。

System.Data.OracleClient.OracleException: ORA-01000: 最大オープン・カーソル数を超えました。


Oracleへの接続は、1ファイルごとにOpen,Closeをしています。
トランザクション処理で、1ファイル(40000件)ごとにコミットするようにしていますので、
1ファイルごとに処理が完結しているはずです。

ファイル数が800ほどあるので、約40000x約800=約3200万件ほどINSERTします。
実行すると、大体2000万〜2500万件あたりで、エラーがでます。


実行している間に、他からのDBへのアクセス等は一切ないはずです・・・。
このアプリでは、以下のソースにある1つのINSERT文以外のSQLは実行していません。
以下のソースで何かし忘れ、閉じ忘れていることはあるでしょうか?

よろしくお願いします。


開発環境: VS.Net 2003
言語  : C# (.NET Framework Data Provider for Oracle )
DB  : Oracle 9i


////////////////////////////////////////////////////
private OracleConnection dbConn;

private void MainProcess(bool flag)
{
 try
 {
  dbConn = new OracleConnection("Data Source=oracle;User Id=test;Password=test;");
  
  ArrayList fileList = new ArrayList();
  // ファイル名一覧を取得
  ・・・・

  string fName = "";
  for (int cnt=0; cnt<fileList.Count; cnt++) // fileList.Count=約800
  {
   // 接続
   dbConn.Open();

   fName = fileList[cnt].ToString();
   if (!setData(fName)) break;

   try { // 接続を閉じる
    dbConn.Close();
   } catch {}
  }
 }
 finally
 {
  try { // 接続を閉じる
   dbConn.Close();
  } catch {}
 }
}


private bool setData(string fName)
{
 OracleTransaction oTrans = null;
 try
 {
  OracleCommand oCmd = new OracleCommand("", dbConn);
  oCmd.CommandText = "INSERT INTO AB_TABLE (AAA, BBB) VALUES(:aaa, :bbb)";
  oCmd.Parameters.Add("aaa", OracleType.Double);
  oCmd.Parameters.Add("bbb", OracleType.Double);
  oCmd.Prepare();
  
  // トランザクション処理開始
  oTrans = dbConn.BeginTransaction();
  oCmd.Transaction = oTrans;

  string line = "";
  double a, b;
  // ファイルの読み込み
  using (StreamReader sr = new StreamReader(fName, Encoding.GetEncoding("Shift_JIS")))
  {
   while ((line = sr.ReadLine()) != null)
   {
    // 1行ごとに a,b の取得
    ・・・

    oCmd.Parameters[0].Value = a;
    oCmd.Parameters[1].Value = b;

    oCmd.ExecuteNonQuery();
   }
  }

  // コミット
  oTrans.Commit();
  return true;
 }
 catch(Exception e)
 {
  if(oTrans != null) oTrans.Rollback();
  return false;
 }
 finally
 {
  if(oTrans != null) oTrans.Dispose();
  oTrans = null;
 }
}
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-09-30 11:27
こんにちは、じゃんぬ です。

Close し忘れがあるのかどうかですが、このソースからだとデバッグしにくいです。
なんせ、try 〜 finally で括るべき場所が全然違いますからね。

正しくはこう。(リンク先は SQL Server ですが、概念は一緒)

 ADO.NET で SQL Server に接続する

Close は finally でやるべきですし、using も使ってください。
Close は null チェックさえしておけば大丈夫です。

それと、例外は完全に無視してるんですね。
本当に例外も何も発生していないんでしょうか?


_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
コウイチ
常連さん
会議室デビュー日: 2003/11/04
投稿数: 48
投稿日時: 2005-09-30 11:58
じゃんぬ さん 返答ありがとうございます。

> Close し忘れがあるのかどうかですが、このソースからだとデバッグしにくいです。
> なんせ、try 〜 finally で括るべき場所が全然違いますからね。
括っているつもりにでいたんですが、
じゃんぬさんのサイト見てみると、括っている場所に問題ありました><

> それと、例外は完全に無視してるんですね。
> 本当に例外も何も発生していないんでしょうか?
このソースだと無視していますが、
例外がでたときはログに落とすようにしています。
投稿文長くなるので、削ってあります。
ORA-01000のエラー以外はでていません。

try〜finallyで、Closeされるように、
usingを使って、SqlConnectionが破棄されるように
書き換えて実行してみます。

書き換えてダメならまた質問すると思いますので、
そのときはよろしくお願いします。
1

スキルアップ/キャリアアップ(JOB@IT)