oracle过程中的临时表

Ale*_*das 7 oracle oracle-11g temporary-tables

我现在处于一种情况。我正在将几个过程从 Mysql 5.0 迁移到 Oracle 11g。Mysql 程序允许我:
1.创建临时表
2. 将数据插入临时表 / 查询这些表 / 做一些处理
3.删除临时表

我一直在搜索并发现我无法在没有EXECUTE IMMEDIATE语句的过程中创建 DDL语句。我尝试使用该语句创建临时表,并立即在其上插入一些值,但它不起作用,因为该表尚不存在。我试图创建一个创建临时表的函数,然后从过程中调用它,但发生了同样的情况。

我需要实现与 MySQL 相同的步骤。这种情况经常发生(有这种“问题”的程序太多了)而且它们非常大。

我有什么选择,你有什么推荐?

Jus*_*ave 9

这取决于您在 MySQL 中创建临时表的原因。

通常,在其他数据库中创建临时表的人这样做是为了解决 Oracle 中不存在的限制,即读取器不会阻止写入器并且写入器不会阻止读取器。在其他数据库中,您通常将数据从永久表复制到临时表,以便您的进程不会阻塞其他需要相同数据的进程。然而,由于 Oracle 提供了多版本读取一致性,这在 Oracle 中不是必需的(或有益的)——您的进程可以处理位于真实表中的数据,而不必担心它会阻塞其他人。如果您处于这种情况,正确的响应就是删除临时表并处理永久表中的数据。

假设您确实需要数据的临时副本,则可以创建全局临时表。您可以像永久表一样在代码之外创建这些表,并在代码中像永久表一样使用它们。全局临时表确保每个会话只能看到会话插入的数据。唯一的区别是您不会在过程中删除和重新创建表的结构。

另一种替代方法是将数据提取到您使用的 PL/SQL 集合中,而不是使用临时表。PL/SQL 集合存储在服务器的 PGA(Oracle 的内存结构之一)中,因此您通常希望限制集合的大小,特别是在有大量数据要处理或可能有许多会话同时处理数据的情况下。你可以做类似的事情

DECLARE
  TYPE emp_tbl IS TABLE OF emp%rowtype;
  l_emps emp_tbl;

  CURSOR emp_cur 
      IS SELECT *
           FROM emp;
BEGIN
  OPEN emp_cur;
  LOOP
    -- Fetch 10 rows at a time from the cursor into the collection.
    -- You'd realistically want a larger limit, something between 100 and 1000 generally
    FETCH emp_cur 
     BULK COLLECT INTO l_emps
    LIMIT 10;

    EXIT WHEN l_emps.COUNT = 0;

    -- An example of manipulating the collection in memory
    FOR i IN 1 .. l_emps.COUNT
    LOOP
      l_emps(i).sal := l_emps(i).sal * 2;
    END LOOP;

    -- And an example of using the collection to update a table
    FORALL i IN 1 .. l_emps.COUNT
      UPDATE emp
         SET sal = l_emps(i).sal
       WHERE empno = l_emps(i).empno;
  END LOOP;
END;
Run Code Online (Sandbox Code Playgroud)

当然,在上面的例子中,简单地发布一个UPDATE将使每个员工的工资翻倍的声明会更简单(也更有效)。