ORA-08103:更改表时不再存在对象

时间:2018-02-02 08:18:48

标签: oracle oracle12c

我有一个存储过程,只需启用特定表的约束。

它已经工作了很长一段时间,但突然(今天),我收到了ORA-08103错误。

导致此错误的原因是什么?

  BEGIN
    FOR c IN (
    SELECT
      c.owner,
      c.table_name,
      c.constraint_name
    FROM user_constraints c
    WHERE c.status = 'DISABLED'
          AND c.table_name IN (
      'TABLE_01', 'TABLE_02', 'TABLE_03', 'TABLE_04'
    )) LOOP
      EXECUTE IMMEDIATE 'ALTER TABLE ' || c.table_name || ' ENABLE CONSTRAINT ' || c.constraint_name;
    END LOOP;
  END;

[更新]

  • 禁用约束
  • 加载批量数据
  • 启用约束

这些是我要遵循的步骤。

首先,我禁用表的约束,然后使用SQLLoader加载批量数据,最后启用禁用的约束,我得到ORA-08103错误。

1 个答案:

答案 0 :(得分:3)

当我们尝试对不存在的对象运行DDL语句时,会发生ORA-08103。啊,但你说

  他们总是在那里。他们永远不会被放弃

数据库对象(如表)在数据字典中有两个标识符:OBJECT_ID和DATA_OBJECT_ID:我们可以在the ALL_OBJECTS view中看到这些标识符。 OBJECT_ID在表的生存期内是常量,但DATA_OBJECT_ID - “包含对象的段的字典对象编号” - 随时间对对象执行DDL时更改。例如,当表被截断或重建索引时。

因此,根据您的情况:ORA-08103错误表示自运行游标后DATA_OBJECT_ID已更改。就在您运行程序时,其他人对其中一个表,约束或基础索引执行了DDL。

这可能是一个不幸的巧合,下次你运行程序时也不会发生这种情况。但是,您可以通过更改运行查询的方式来最小化另一次出现的可能性:

declare
    tabs dbms_debug_vc2coll := dbms_debug_vc2coll ('TABLE_01', 'TABLE_02', 'TABLE_03', 'TABLE_04');
BEGIN
    for idx in 1..tabs.count() loop
        FOR c IN (
            SELECT
                c.owner,
                c.table_name,
                c.constraint_name
            FROM user_constraints c
            WHERE c.table_name = tabs(idx)
            AND c.status = 'DISABLED'
          ) LOOP
             EXECUTE IMMEDIATE 'ALTER TABLE ' || c.table_name || ' ENABLE CONSTRAINT ' || c.constraint_name;
        END LOOP;
    END LOOP;
END;

启用约束需要时间(因为需要验证它们)。因此,逐个选择表会减少您需要DATA_OBJECT_ID保持修复的时间。

  

“您的程序如何最大限度地减少出现同样错误的可能性?”

您的光标选择所有四个表,因此选择所有四个DATA_OBJECT_ID。假设在TABLE_01上启用约束时,另一个会话会修改TABLE_04。当您的过程转到TABLE_04时,DATA_OBJECT_ID已更改,您将获得ORA-08103。

但是如果您运行我的代码版本并不重要,因为在您准备好处理之前,您不会为TABLE_04选择DATA_OBJECT_ID。所以你会得到改变后的DATA_OBJECT_ID(不知道它被改变了。