2

トランザクション内に「ON COMMIT DELETE ROWS」オプションを使用して複数の Oracle 一時テーブルを作成する C# コードがあります。

トランザクション内で、一連の行をさまざまな一時テーブルに挿入します。一部のシナリオでは、特定の一時テーブルを切り捨てて、そのテーブルで新たに開始できるようにする必要がありますが、他の一時テーブルはそのままにしておきます。

特定の一時テーブルが切り捨てられただけでなく、すべての一時テーブルが切り捨てられているため、切り捨てを実行するときにOracleが暗黙のCOMMITを実行している必要があることがわかりました。

OK、TruncateコマンドはDDLコマンドと見なされることを他の場所で読みました。そのため、コミットが処理され、「ON COMMIT DELETE ROWS」一時テーブルがクリアされます。

それが本当なら、新しい一時テーブルを作成する行為もDDLコマンドではないでしょうか?また、同じコミットをトリップして他のすべての一時テーブルをクリアしますか? もしそうなら、私はその行動を見たことがありません。コードで新しい一時テーブルを作成しましたが、新しい一時テーブルが作成された後、以前に作成された一時テーブルの行がそのまま残っていることがわかりました。

問題を示すいくつかの C# コードを次に示します (ヘルパー ルーチンはここには含まれていません)。

private void RunTest()
{
  if (_oc == null)
    _oc = new OracleConnection("data source=myserver;user id=myid;password=mypassword");

  _oc.Open();
  _tran = _oc.BeginTransaction();

  string tt1 = "DMTEST1";
  AddTempTable(tt1, false);
  int TempTableRowCount0 = GetTempTableRowCount(tt1);

  AddRows(tt1, 5);
  int TempTableRowCount10 = GetTempTableRowCount(tt1);

  string tt2 = "DMTEST2";
  AddTempTable(tt2, false);
  int TempTableRowCount12 = GetTempTableRowCount(tt1); // This will have the same value as TempTableRowCount10
  AddRows(tt2, 6);
  int TempTableRowCount13 = GetTempTableRowCount(tt2); // This will have the same value as TempTableRowCount10

  string tt3 = "DMTEST3";
  AddTempTable(tt3, true); // The TRUE argument which does a TRUNCATE against the DMTEST3 table is the problem
  int TempTableRowCount14 = GetTempTableRowCount(tt1); // This will return 0, it should be = TempTableRowCount10
  int TempTableRowCount15 = GetTempTableRowCount(tt2); // This will return 0, it should be = TempTableRowCount13

  _tran.Commit();
  _tran = null;
  int TempTableRowCount20 = GetTempTableRowCount(tt1); // This should be 0 because the transaction was committed 
  int TempTableRowCount21 = GetTempTableRowCount(tt2); // and the temp tables are defined as "ON COMMIT DELETE ROWS"
}

private void AddTempTable(string TableName, bool Truncate)
{
  IDbCommand ocmd = new OracleCommand();
  ocmd.Connection = _oc;
  if (!TableExists(TableName))
  {
    ocmd.CommandText = string.Format("CREATE GLOBAL TEMPORARY TABLE {0} ({1}) ON COMMIT DELETE ROWS", TableName, "FIELD1 Float");
    int rc = ocmd.ExecuteNonQuery();
  }
  if (Truncate)
  {
    ocmd.CommandText = "TRUNCATE TABLE " + TableName;
    int rc = ocmd.ExecuteNonQuery();
  }
}
4

1 に答える 1

5

Oracle では、実行時にグローバル一時テーブルを作成しません。システムをデプロイするときに一度作成します。各セッションは、一時テーブルの独自の「コピー」を自動的に取得します。

また、TRUNCATE を回避できる場合はお勧めします。つまり、コミット時にデータが消える ON COMMIT DELETE ROWS に依存できる場合、それが最も効率的な方法です。

あなたの他の質問に答えるために(「CREATE GLOBAL TEMPORARYはコミットしていないようです」)-私は自分で試してみましたが、CREATE GLOBAL TEMPORARYは実際にコミットしているようです。私のテストケース:

create global temporary table test1 (n number) on commit delete rows;
insert into test1 values (1);
--Expected: 1
select count(*) from test1;
commit;
--Expected: 0
select count(*) from test1;
insert into test1 values (2);
--Expected: 1
select count(*) from test1;
create global temporary table test2 (n number) on commit delete rows;
--Expected: 0
select count(*) from test1;
commit;
--Expected: 0
select count(*) from test1;
于 2012-06-07T02:55:10.323 に答える