禁用Oracle中的所有表约束

时间:2020-03-06 14:40:40  来源:igfitidea点击:

如何使用单个命令禁用Oracle中的所有表约束?
可以是单个表,表列表,也可以是所有表。

解决方案

看起来我们不能使用单个命令来完成此操作,但是这是我能找到的最接近的命令。

这不是一个命令,但是这是我的操作方法。下面的脚本被设计为可以在SQL * Plus中运行。注意,我故意将其编写为仅在当前模式下工作。

set heading off

spool drop_constraints.out

select
    'alter table ' || 
    owner || '.' || 
    table_name || 
    ' disable constraint ' || -- or 'drop' if you want to permanently remove
    constraint_name || ';'
from
    user_constraints;

spool off

set heading on

@drop_constraints.out

要限制删除的内容,请在filter语句中添加一个where子句:-

  • 对constraint_type进行过滤以仅删除特定类型的约束
  • 对table_name进行过滤以仅对一个或者几个表执行此操作。

要在当前架构上运行以外的其他内容,请修改select语句以从all_constraints中进行选择,而不是从user_constraints中进行选择。

请注意,由于某种原因,我无法使下划线在上一段中不像斜体一样起作用。如果有人知道如何解决,请随时编辑此答案。

可以很简单地基于DBA / ALL / USER_CONSTRAINTS系统视图在PL / SQL中编写脚本,但是各种细节并不听起来那么简单。我们必须注意完成的顺序,还必须考虑唯一索引的存在。

该顺序很重要,因为我们不能删除由外键引用的唯一键或者主键,并且在其他模式中的表上可能有自己引用主键的外键,因此除非我们拥有ALTER ANY TABLE特权,否则无法放弃这些PK和英国。另外,我们不能将唯一索引转换为非唯一索引,因此必须先删除它才能删除约束(因此,将唯一约束作为非约束支持的"实际"约束实现总是更好-唯一索引)。

最好避免写出临时假脱机文件。使用PL / SQL块。我们可以从SQL * Plus运行此程序,或者将其放入程序包或者过程中。那里有USER_TABLES的联接,以避免视图约束。

我们不太可能真的想禁用所有约束(包括NOT NULL,主键等)。我们应该考虑将约束类型放入WHERE子句中。

BEGIN
  FOR c IN
  (SELECT c.owner, c.table_name, c.constraint_name
   FROM user_constraints c, user_tables t
   WHERE c.table_name = t.table_name
   AND c.status = 'ENABLED'
   AND NOT (t.iot_type IS NOT NULL AND c.constraint_type = 'P')
   ORDER BY c.constraint_type DESC)
  LOOP
    dbms_utility.exec_ddl_statement('alter table "' || c.owner || '"."' || c.table_name || '" disable constraint ' || c.constraint_name);
  END LOOP;
END;
/

再次启用约束有点棘手,我们需要先启用主键约束,然后才能在外键约束中引用它们。这可以通过使用constraint_type上的ORDER BY来完成。 " P" =主键," R" =外键。

BEGIN
  FOR c IN
  (SELECT c.owner, c.table_name, c.constraint_name
   FROM user_constraints c, user_tables t
   WHERE c.table_name = t.table_name
   AND c.status = 'DISABLED'
   ORDER BY c.constraint_type)
  LOOP
    dbms_utility.exec_ddl_statement('alter table "' || c.owner || '"."' || c.table_name || '" enable constraint ' || c.constraint_name);
  END LOOP;
END;
/

在"禁用"脚本中,order by子句应为:

ORDER BY c.constraint_type DESC, c.last_change DESC

此子句的目标是按正确的顺序禁用约束。

使用以下光标禁用所有约束。并更改查询以启用约束...

DECLARE

cursor r1 is select * from user_constraints;
cursor r2 is select * from user_tables;

BEGIN
  FOR c1 IN r1
  loop
    for c2 in r2
    loop
       if c1.table_name = c2.table_name and c1.status = 'ENABLED' THEN
        dbms_utility.exec_ddl_statement('alter table ' || c1.owner || '.' || c1.table_name || ' disable constraint ' || c1.constraint_name);
       end if;
    end loop;
  END LOOP;
END;
/