PL/SQL Append_Values 提示给出错误信息

Posted

技术标签:

【中文标题】PL/SQL Append_Values 提示给出错误信息【英文标题】:PL/SQL Append_Values Hint gives error message 【发布时间】:2014-02-14 23:08:09 【问题描述】:

我在使用 PL/SQL 对 Oracle 表执行大量插入操作时遇到问题。我的查询逐行进行,查询对每一行进行计算以确定它需要插入另一个表的行数。传统的插入工作,但代码需要很长时间才能运行大量行。为了加快插入速度,我尝试使用Append_Values 提示,如下例所示:

BEGIN
FOR iter in 1..100 LOOP
INSERT /*+ APPEND_VALUES*/ INTO test_append_value_hint values (iter);
END LOOP;
END;

执行此操作时收到以下错误消息:

ORA-12838: cannot read/modify an object after modifying it in parallel
ORA-06512: at line 3
12838. 00000 -  "cannot read/modify an object after modifying it in parallel"
*Cause:    Within the same transaction, an attempt was made to add read or
           modification statements on a table after it had been modified in parallel
           or with direct load. This is not permitted.
*Action:   Rewrite the transaction, or break it up into two transactions
           one containing the initial modification and the second containing the
           parallel modification operation.

有没有人知道如何使这段代码工作,或者如何快速将大量行插入另一个表?

【问题讨论】:

行来自哪里?你真的只想插入数字 1 到 100 吗?还是您真的从某个来源提取数据? 我得到了一个表格,其中包含个人以及个人注册计划的开始日期和结束日期。对于输出表,我需要为个人注册该计划的每个月/年提供一行。因此,如果一个人的开始日期为 2012 年 12 月 21 日,结束日期为 2013 年 4 月 10 日,我需要该人的五条记录(12/2012、01/2013、02/2013、03 的记录) /2013 和 04/2013)。我的没有 APPEND_VALUES 提示的 PL/SQL 代码适用于小表,但我的表有大约一百万行。 宁可不要使用它。尤其是从 PL/SQL 中,应该可以将代码重写为纯 SQL “insert /* +APPEND */ ..select”。此外,此解决方案无法扩展,因为只有一个会话可以同时附加到表中。此外,直接路径写入仅在某些情况下使用,例如表上没有 FK。如果你真的想加速你的 ETL,请使用ALTER SESSION FORCE PARALLEL DML 【参考方案1】:

您收到此错误是因为您的每个 INSERT 都作为单独的 DML 语句执行。 Oracle 会阻止对使用直接路径插入添加数据的表进行读/写,直到提交为止。 从技术上讲,您可以使用 PL/SQL 集合和 FORALL:

SQL> declare
  2   type array_t is table of number index by pls_integer;
  3   a_t array_t;
  4  begin
  5    for i in 1..100 loop
  6      a_t(i) := i;
  7    end loop;
  8    forall i in 1..100
  9      insert /*+ append_values */ into t values (a_t(i));
 10  end;
 11  /

但贾斯汀提出的问题是实际问题 - 您的数据来自哪里,为什么不能使用通常的 INSERT /*+ append */ INTO ... SELECT FROM 方法?

【讨论】:

【参考方案2】:

您好,要求您在插入后使用提交,如下所示:

BEGIN
FOR iter in 1..100 LOOP
INSERT /*+ APPEND_VALUES*/ INTO test_append_value_hint values (iter);
COMMIT;
END LOOP;
END;

【讨论】:

是的,+1 - 这不是导致错误的附加提示 - 这是 Oracle 在修改表后拒绝再次修改表的事实。【参考方案3】:

如果不提交第一个事务,我们就无法在一个表中执行 2 个 DML 事务。因此会抛出这个错误。

所以,提交您在该表中的上一个事务并继续第二个事务。

【讨论】:

以上是关于PL/SQL Append_Values 提示给出错误信息的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL Developer 错误提示框相关设置

PL/SQL Oracle 无提示错误

这是不是可以在 PL/SQL 中执行存储过程时每次都提示?

PL/SQL登陆就会提示TNS协议适配器错误,这啥问题。

PL/SQL 函数中的 XmlRoot、XmlElement、InsertChildXml 给出 PLS-00201 必须声明标识符

创建带有 2 个游标、一个参数并从表中给出结果的 PL/SQL 脚本?