截断事务中的预言机临时表,将截断 *ALL* 临时表

本文关键字:临时表 ALL 预言机 事务 | 更新日期: 2023-09-27 18:36:33

我有一些 C# 代码,可以在事务中使用"提交删除行"选项创建多个 Oracle 临时表。

在事务内部,我将在各种临时表中插入一堆行。 在某些情况下,我需要截断特定的临时表,以便我可以重新开始使用该表,但保留其他临时表。

我发现当您执行截断时,Oracle 必须执行隐式 COMMIT 操作,因为不仅特定的临时表被截断,而且我的所有临时表都被截断了。

好的,我在其他地方读到截断命令被认为是 DDL 命令,这就是正在处理提交的原因,这会导致我的"提交删除行"临时表被清除。

如果这是真的,那么创建新临时表的行为是否也是 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();
  }
}

截断事务中的预言机临时表,将截断 *ALL* 临时表

在 Oracle 中,您不会在运行时创建全局临时表。部署系统时只需创建一次。每个会话都会自动获得自己的临时表"副本"。

另外,如果您可以避免TRUNCATE,我会推荐它 - 即,如果您可以依靠提交删除行,这会导致提交时数据消失,那么这是最有效的方法。

回答您的另一个问题("创建全局临时似乎没有提交")-我自己尝试过,在我看来,创建全局临时确实确实提交。我的测试用例:

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;