我有一个存储过程,它只是启用特定表的约束。
它已经运行了很长一段时间,但突然(今天),我得到了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错误。
发布于 2018-02-02 08:51:33
当我们尝试对不存在的对象运行DDL语句时,就会发生ORA-08103。啊,但你说
他们总是在那里。他们永远不会被丢弃
数据库对象(如表)在数据字典中有两个标识符,OBJECT_ID和DATA_OBJECT_ID:我们可以在对象视图中看到这些标识符。在表的生存期内,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_IDs。假设另一个会话在启用对TABLE_04的约束时修改TABLE_01。当您的过程转到TABLE_04时,DATA_OBJECT_ID已经更改,您将得到ORA-08103。
但是,如果您正在运行我的代码版本,这并不重要,因为在准备好处理它之前,您不会选择DATA_OBJECT_ID for TABLE_04。因此,您将得到已更改的DATA_OBJECT_ID (而不知道它已被更改)。
https://stackoverflow.com/questions/48578480
复制相似问题