自治事务中的 Oracle DDL

标签 oracle transactions constraints ddl ora-00054

我需要在 Oracle 数据库上执行一堆(最多约 1000000 条)sql 语句。这些语句最后应该导致引用一致的状态,如果发生错误,所有语句都应该回滚。这些语句不是按引用顺序出现的。因此,如果启用了外键约束,其中一个语句可能会导致外键冲突,即使此冲突将通过稍后执行的语句来修复。

我尝试先禁用外键,然后在执行所有语句后启用它们。我以为当实际发生外键违规时我可以回滚。但是我错了,我发现 Oracle 中的每个 DDL 语句都以提交开始,因此无法以这种方式回滚语句。这是我禁用外键的脚本:

begin 
  for i in (select constraint_name, table_name from user_constraints
            where constraint_type ='R' and status = 'ENABLED') 
    LOOP execute immediate 'alter table '||i.table_name||' disable constraint 
                           '||i.constraint_name||''; 
  end loop;
end;

经过一番研究,我发现建议在自治事务中执行 DDL 语句,就像在这种情况下一样。所以我尝试在自治事务中运行 DDL 语句。这导致了以下错误:

ORA-00054: 资源繁忙并使用指定的 NOWAIT 获取

我猜这是因为主事务在表上仍然有 DDL 锁。

我在这里做错了什么,还是有其他方法可以使这种情况起作用?

最佳答案

有几种潜在的方法。

首先要考虑的是,您在表级别所做的任何事情都将适用于使用该表的所有 session 。如果您没有对该表的独占访问权限,您可能不想删除/重新创建约束,或禁用/启用它们。

要考虑的第二件事是您可能不希望回滚一百万次插入/更新。回滚可能很慢。

通常我会加载到一个临时表中。然后从临时表向目标表执行一次 INSERT。作为单个语句,Oracle 将在最后应用所有检查约束。

如果您无法通过临时表(例如更新现有数据),请在开始之前进行约束 deferrable initially immediate .然后,在您的 session 中,

SET CONSTRAINTS emp_job_nn, emp_salary_min DEFERRED;

然后,您可以应用更改,并在提交时验证约束。

你应该熟悉 DML error logging因为它可以帮助识别导致违规的任何行。

关于自治事务中的 Oracle DDL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2353592/

相关文章:

swift - 无法为特定设备自定义 UITableViewCell

sql - Oracle SQL 中的检查约束

oracle - 创建oracle包遇到PLS-00103 : Encountered the symbol "CREATE"

sql - oracle 使用 REGEXP_SUBSTR(AGGREGATOR ,'[^;]+' ,1,LEVEL) 查询速度很慢

java - Oracle 在提交和选择之间滞后

sqlite - SQLite 中的 SAVEPOINT 机制

java - MySQL 从表中删除或更新表列以将其标记为已删除?

sql-server - 如果更新不成功如何回滚?

ios - ScrollView contentView 大小没有相应改变

oracle - JUnit/HSQLDB : How to get around errors with Oracle syntax when testing using HSQLDB (no privilege and/or no DUAL object)