【问题标题】:Oracle, concurrency and global temporary tablesOracle、并发和全局临时表
【发布时间】:2019-08-08 17:58:30
【问题描述】:

我有一个 ruby​​ 应用程序,可以从不同的视图从 oracle 加载数据。每个查询都有一个很大的 IN 子句(数千个 id),我遇到了 PGA 限制错误。我通过创建一个包来解决这个问题,将 ID 插入到全局临时表中,并针对该表运行带有 exists 子句的 sql。它在不并发时运行良好,但在同时执行时,我得到一个(ORA-00955:名称已被现有对象使用)。

  CREATE GLOBAL TEMPORARY TABLE temp_ids_table (
    id NUMBER
  )
  on commit preserve rows;
  /

--

  CREATE OR REPLACE PACKAGE test.bulk_query
  IS
    TYPE temp_ids IS TABLE OF NUMBER;

    FUNCTION run_query(ids IN temp_ids, query IN VARCHAR2) RETURN sys_refcursor;

  END bulk_query;
  /

  CREATE OR REPLACE PACKAGE BODY test.bulk_query
  IS

    FUNCTION run_query(ids IN temp_ids, query IN VARCHAR2) RETURN sys_refcursor
    IS
      dataset SYS_REFCURSOR;
    BEGIN
      FOR i IN 1 .. ids.count LOOP
        execute immediate 'INSERT INTO TEMP_IDS_TABLE (ID) VALUES (:id)' using ids(i);
      END LOOP;

      OPEN dataset FOR query;

      commit;

      RETURN dataset;
    END;
  END bulk_query;
  /

【问题讨论】:

  • ORA-00955 的堆栈跟踪指向您发布的代码中的哪一行?
  • 为什么在这种情况下根本需要GLOBAL TEMPORARY TABLE。可以使用简单的IN 子句来完成。

标签: ruby oracle plsql concurrency


【解决方案1】:

只创建一次(全局临时)表,然后再执行其他任何操作。它将是“永久的”,意思是:它的描述将保持不变; 不要删除该表(然后一次又一次地创建它)。

让任何人(通过您编写的程序)根据需要多次使用它。每个人都只会看到自己的数据;他们将无法影响其他人的行。

因为,您似乎正在尝试为每个运行该进程的用户创建它 - 这是错误的。


顺便说一句,为什么是动态SQL?为什么不直接将这些值插入到表格中?

【讨论】:

  • 谢谢。我确实只创建了一次全局临时表,我没有删除它。如何在不循环数组的情况下将数组值插入表中?
  • 是什么导致“ORA-00955:名称已被现有对象使用”?
  • 我不知道。只有当我同时运行多个查询时才会发生这种情况。我希望这里有人能提供一些启示。
  • 这是 - 您发布的 - 您正在运行的整个代码吗?
  • 这是我所有的plsql代码。我有调用这个 plsql 函数的 ruby​​ 代码。基本上我传入一个 id 数组和要执行的 sql 语句。基本上我多次调用这个函数,传入不同的 sql 查询。我传递的一个示例 sql 语句是这样的“select * from foobar A where exists (select null from temp_ids_table B where A.id = B.id)”
猜你喜欢
  • 1970-01-01
  • 2017-10-02
  • 2023-03-27
  • 1970-01-01
  • 2016-04-02
  • 1970-01-01
  • 2012-02-13
  • 1970-01-01
  • 2010-09-12
相关资源
最近更新 更多