Sql Oracle 10中的本地临时表(用于存储过程的范围)

Sql Oracle 10中的本地临时表(用于存储过程的范围),sql,database,oracle,stored-procedures,temp-tables,Sql,Database,Oracle,Stored Procedures,Temp Tables,我是甲骨文的新手。我需要在存储过程中处理大量数据。我正在考虑使用临时桌子。我使用连接池,应用程序是多线程的 是否有一种方法可以创建临时表,即为每次对存储过程的调用创建不同的表实例,这样来自多个存储过程调用的数据就不会混淆?如果您使用的是事务(而不是会话)级临时表,那么这可能已经满足了您的需要。。。只要每个调用只包含一个事务?(您没有提供足够的详细信息来说明情况是否如此) 因此,要明确的是,只要每个调用只包含一个事务,那么使用连接池就无关紧要了,因为在每次提交或回滚之后,数据都会从临时表中清除 (

我是甲骨文的新手。我需要在存储过程中处理大量数据。我正在考虑使用临时桌子。我使用连接池,应用程序是多线程的


是否有一种方法可以创建临时表,即为每次对存储过程的调用创建不同的表实例,这样来自多个存储过程调用的数据就不会混淆?

如果您使用的是事务(而不是会话)级临时表,那么这可能已经满足了您的需要。。。只要每个调用只包含一个事务?(您没有提供足够的详细信息来说明情况是否如此)

因此,要明确的是,只要每个调用只包含一个事务,那么使用连接池就无关紧要了,因为在每次提交或回滚之后,数据都会从临时表中清除


(另一个选项是在每次调用中使用EXECUTE IMMEDIATE创建一个唯一命名的临时表。但不确定其性能如何。)

如果您使用的是事务(而不是会话)级临时表,那么这可能已经满足了您的要求。。。只要每个调用只包含一个事务?(您没有提供足够的详细信息来说明情况是否如此)

因此,要明确的是,只要每个调用只包含一个事务,那么使用连接池就无关紧要了,因为在每次提交或回滚之后,数据都会从临时表中清除


(另一种选择是在每次调用中使用EXECUTE IMMEDIATE创建一个唯一命名的临时表。但不确定其性能如何。)

在Oracle中,几乎不需要在运行时创建对象

全局临时表很可能是解决您的问题的最佳解决方案,但是由于您还没有确切说明为什么需要临时表,我建议您首先检查临时表是否必要;有一半的时间,您可以使用一个SQL完成您可能认为需要多个查询的任务

也就是说,我过去在需要为同一会话中的多个上下文在表中维护单独的“空间”的应用程序中非常成功地使用了全局临时表;这是通过添加一个初始设置为1的附加ID列(例如“CALL_ID”)来实现的,随后对过程的调用将增加该ID。必须在某个地方使用全局变量来记住该ID,例如在包体中声明的包全局变量。例如:

PACKAGE BODY gtt_ex IS
   last_call_id integer;
   PROCEDURE myproc IS
      l_call_id integer;
   BEGIN
      last_call_id := NVL(last_call_id, 0) + 1;
      l_call_id      := last_call_id;
      INSERT INTO my_gtt VALUES (l_call_id, ...);
      ...
      SELECT ... FROM my_gtt WHERE call_id = l_call_id;
   END;
END;

您会发现GTT即使在高并发性的情况下也表现得非常好,肯定比使用普通表要好。最佳做法是设计应用程序,使其永远不需要删除临时表中的行—因为会话结束时GTT会自动清除。

在Oracle中,几乎不需要在运行时创建对象

全局临时表很可能是解决您的问题的最佳解决方案,但是由于您还没有确切说明为什么需要临时表,我建议您首先检查临时表是否必要;有一半的时间,您可以使用一个SQL完成您可能认为需要多个查询的任务

也就是说,我过去在需要为同一会话中的多个上下文在表中维护单独的“空间”的应用程序中非常成功地使用了全局临时表;这是通过添加一个初始设置为1的附加ID列(例如“CALL_ID”)来实现的,随后对过程的调用将增加该ID。必须在某个地方使用全局变量来记住该ID,例如在包体中声明的包全局变量。例如:

PACKAGE BODY gtt_ex IS
   last_call_id integer;
   PROCEDURE myproc IS
      l_call_id integer;
   BEGIN
      last_call_id := NVL(last_call_id, 0) + 1;
      l_call_id      := last_call_id;
      INSERT INTO my_gtt VALUES (l_call_id, ...);
      ...
      SELECT ... FROM my_gtt WHERE call_id = l_call_id;
   END;
END;

您会发现GTT即使在高并发性的情况下也表现得非常好,肯定比使用普通表要好。最佳做法是设计应用程序,使其永远不需要删除临时表中的行,因为会话结束时GTT会自动清除。

您说您是Oracle新手。我猜您已经习惯了SQL Server,在那里使用临时表是很常见的。Oracle的工作方式有所不同,因此它不太常见,因为它不太必要

请记住,使用临时表会带来以下开销:
  • 读取数据以填充临时表
  • 将临时表数据写入文件
  • 在流程启动时从临时表读取数据大多数活动在帮助您完成任务方面是无用的。一个更好的办法是看看您是否可以在一次操作中完成所有事情,最好是纯SQL



    顺便提一下,您提到的连接池引发了另一个问题。处理大量数据的进程不适合在OLTP模式下运行。您确实应该考虑启动后台(即异步进程),可能是数据库作业,以运行存储过程。如果您希望定期运行此作业,这一点尤其正确,因为我们可以使用DBMS_SCHEDULER来自动管理这些内容。

    您说您是Oracle的新手。我猜您已经习惯了SQL Server,在那里使用临时表是很常见的。Oracle的工作方式有所不同,因此它不太常见,因为它不太必要

    请记住,使用临时表会带来以下开销:
  • 读取数据以填充临时表
  • 将临时表数据写入文件
  • 在流程启动时从临时表读取数据大多数活动在帮助您完成任务方面是无用的。一个更好的办法是看看您是否可以在一次操作中完成所有事情,最好是纯SQL


    顺便提一下,您提到的连接池引发了另一个问题。处理大量数据的进程不适合在OLTP模式下运行。你真的应该考虑发起反击。