ORA-12838 如何在删除和插入之前预测试查询?

huangapple go评论60阅读模式
英文:

ORA-12838 How to pre-test a query before a delete and insert?

问题

Error: ORA-12838: cannot read/modify an object after modifying it in parallel. Committing the delete defeats the purpose of course.

Is there a way I can use an uncommitted delete followed by an insert that can be rolled back in case of an issue during, e.g., the insert writes?

Code:

DECLARE
    tbl_count number;
    sql_stmt long;

BEGIN
    SELECT 
        COUNT(*) 
    INTO 
        tbl_count  
    FROM 
        ALL_TABLES   
    WHERE
        table_name = 'XXX';

    IF(tbl_count <= 0) THEN
      sql_stmt:=
    'CREATE TABLE XXX (
                   AA varchar2(255),
                   BB DATE
                   )';

    EXECUTE IMMEDIATE sql_stmt;

    END IF;

END;

BEGIN
    EXECUTE IMMEDIATE 'DELETE FROM XXX';

INSERT INTO
    XXX
SELECT
    "AA",
    TO_DATE("BB",'YYYY-MM-DD') AS BB
FROM
    "XXX_STG";

COMMIT;

EXCEPTION 
    WHEN OTHERS THEN
      ROLLBACK;
      RAISE;
END;

It doesn't yet make sense conceptually; would appreciate some help/ideas.

英文:

Error: ORA-12838: cannot read/modify an object after modifying it in parallel. Committing the delete defeats the purpose of course.

Is there a way I can use an uncommited delete followed by an insert that can be rolled back in case of an issue during e.g. the insert writes?

Code:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

DECLARE
    tbl_count number;
    sql_stmt long;

BEGIN
    SELECT 
        COUNT(*) 
    INTO 
        tbl_count  
    FROM 
        ALL_TABLES   
    WHERE
        table_name = &#39;XXX&#39;;

IF(tbl_count &lt;= 0) THEN
  sql_stmt:=
&#39;CREATE TABLE XXX (
                   AA varchar2(255),
                   BB DATE
                   )&#39;;

EXECUTE IMMEDIATE sql_stmt;

END IF;

END;

BEGIN
    EXECUTE IMMEDIATE &#39;DELETE FROM XXX&#39;;

INSERT INTO
    XXX
SELECT
    &quot;AA&quot;,
    TO_DATE(&quot;BB&quot;,&#39;YYYY-MM-DD&#39;) AS BB
FROM
    &quot;XXX_STG&quot;;

COMMIT;

EXCEPTION 
    WHEN OTHERS THEN
      ROLLBACK;
      RAISE;
END;

<!-- end snippet -->

It does't yet make sense conceptually, would appreciate some help/ideas.

答案1

得分: 4

ORA-12838与事务本身无关,而是与是否使用并行 DML(数据操纵语言)来修改表格有关。如果您不使用并行DML,那么您可以在同一个事务中进行DELETE然后INSERT而不会出现任何问题。

SQL> create table t as
  2  select * from dba_objects;
  
  Table created.
  
SQL>
SQL> begin
  2    delete from t;
  3    insert into t
  4    select * from dba_objects;
  5    commit;
  6  end;
  7  /

PL/SQL procedure successfully completed.

SQL>
SQL>
SQL> alter session force parallel dml;

Session altered.

SQL> begin
  2    delete from t;
  3    insert into t
  4    select * from dba_objects;
  5    commit;
  6  end;
  7  /
begin
*
ERROR at line 1:
ORA-12838: cannot read/modify an object after modifying it in parallel
ORA-06512: at line 3

如果您想保留并行处理,同时也想在需要时保留已删除行的记录,可以执行类似以下操作:

  • 创建备份表 backup_table as select * from table
  • 截断表
  • 插入数据到表 select ...

顺便提一下,这个限制在23c版本中已经取消了。

英文:

ORA-12838 is not related to transactions per se, but is about if you are using parallel dml to modify a table. If you do not use parallel DML, then you can DELETE-then-INSERT in the same transaction without any issues.

SQL&gt; create table t as
  2  select * from dba_objects;

Table created.

SQL&gt;
SQL&gt; begin
  2    delete from t;
  3    insert into t
  4    select * from dba_objects;
  5    commit;
  6  end;
  7  /

PL/SQL procedure successfully completed.

SQL&gt;
SQL&gt;
SQL&gt; alter session force parallel dml;

Session altered.

SQL&gt; begin
  2    delete from t;
  3    insert into t
  4    select * from dba_objects;
  5    commit;
  6  end;
  7  /
begin
*
ERROR at line 1:
ORA-12838: cannot read/modify an object after modifying it in parallel
ORA-06512: at line 3

If you want to keep the parallel processing, and also keep a record of the deleted rows "just in case", you could do something like

  • create backup_table as select * from table
  • truncate table
  • insert into table select ...

This restriction is lifted in 23c btw.

huangapple
  • 本文由 发表于 2023年6月8日 10:45:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76428271.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定