暂时禁用Oracle数据库中的约束

时间:2015-12-31 21:29:59

标签: sql database oracle

我有一个Oracle SQL删除语句需要很长时间才能运行。它非常简单,如:

delete from table
where fy = 2016

我还手动尝试删除TOAD中需要删除的~2500行之一,删除单行大约需要6分钟。

我认为这样做的原因是该表有很多约束,所以我想知道我是否可以某种方式更改我的删除语句,以便它可以绕过约束或暂时禁用它们做得更快?如果是这样,我怎样才能重新启用它们?

2 个答案:

答案 0 :(得分:4)

删除单行6分钟听起来不像是表上的约束问题。有三种合理可能的机制会导致这种性能问题。根据我的经验,最不可能的是

  1. 该表是一个或多个大型子表的父级。子表具有对父表的强制外键引用,但外键列未在子表中编制索引。如果是这种情况,问题是Oracle每次从父级删除行时都必须对表进行全面扫描,以验证没有孤立。您可以转到每个子表并删除外键,但几乎可以肯定的是索引子表中的外键列。您想要使用无索引的外键是非常罕见的。
  2. 桌子上有一个触发器,触发器正在做一些需要6分钟的事情。您必须查看触发器代码才能确切了解在那里花了多长时间。
  3. 您正在进行单行删除作为事务,并且您有一个on commit物化视图,需要根据更改进行更新。很难想出一种方法来构建这样的东西,需要花费6分钟才能运行但是肯定有办法让它变慢。

答案 1 :(得分:0)

如你所说;原因是该表的外键。您应该在删除之前禁用该键,并在删除后启用它们。您可以使用以下脚本来启用/禁用特定表的密钥。

declare
  l_constraint_sql varchar2(1024);
  l_op_type varchar2(10) := 'ENABLE';

begin
  -- Test statements here
  for r in (select a.*
              from user_constraints a, user_constraints b
             where a.constraint_type = 'R'
               and a.r_constraint_name = b.constraint_name
               and a.r_owner = b.owner
               and a.owner = 'FAYDIN' --schema
               and b.table_name = 'GEN_KOD' --table you want to disable constraints
            ) loop
    l_constraint_sql := 'alter table ' || r.TABLE_NAME ||
                        ' ' || l_op_type || '  constraint ' || r.CONSTRAINT_NAME || '';

    --uncomment following line to execute                    
    --execute immediate l_constraint_sql;
    dbms_output.put_line(l_constraint_sql);

  end loop;
end;