在Oracle中禁用所有表约束
如何使用单个命令禁用Oracle中的所有表约束? 这可以是单个表格,表格列表或所有表格。
最好避免写出临时的假脱机文件。 使用PL / SQL块。 你可以从SQL * Plus运行这个或者把这个东西放到一个包或程序中。 与USER_TABLES的连接可以避免视图约束。
你不可能真的想禁用所有的约束(包括NOT NULL,主键等)。 你应该考虑把constraint_type放在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; /
要计算约束之间的依赖关系:
SET Serveroutput ON 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' ORDER BY c.constraint_type DESC,c.last_change DESC ) LOOP FOR D IN (SELECT P.Table_Name Parent_Table,C1.Table_Name Child_Table,C1.Owner,P.Constraint_Name Parent_Constraint, c1.constraint_name Child_Constraint FROM user_constraints p JOIN user_constraints c1 ON(p.constraint_name=c1.r_constraint_name) WHERE(p.constraint_type='P' OR p.constraint_type='U') AND c1.constraint_type='R' AND p.table_name=UPPER(c.table_name) ) LOOP dbms_output.put_line('. Disable the constraint ' || d.Child_Constraint ||' (on table '||d.owner || '.' || d.Child_Table || ')') ; dbms_utility.exec_ddl_statement('alter table ' || d.owner || '.' ||d.Child_Table || ' disable constraint ' || d.Child_Constraint) ; END LOOP; END LOOP; END; /
这不是一个单一的命令,但这是我如何做到这一点。 以下脚本被devise为在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
要限制你放弃的内容,请在select语句中添加一个where子句:
- 过滤constraint_type以仅删除特定types的约束
- 在table_name上过滤只为一个或几个表执行此操作。
要在多于当前模式下运行,请修改select语句以从all_constraints而不是user_constraints中进行select。
请注意 – 出于某种原因,我无法使下划线在上一段中不像斜体。 如果有人知道如何解决这个问题,请随时编辑这个答案。
这可以很简单地基于DBA / ALL / USER_CONSTRAINTS系统视图在PL / SQL中编写脚本,但各种细节并不像听起来那么微不足道。 你必须小心它的完成顺序,你也必须考虑到独特索引的存在。
顺序非常重要,因为您不能删除由外键引用的唯一键或主键,而在其他模式的表中可能会有自己的引用主键的外键,所以除非您具有ALTER ANY TABLE特权,否则您不能放弃那些PK和UKs。 此外,您不能将唯一索引切换为非唯一索引,因此必须将其删除才能删除约束(因此,将唯一约束作为非真实约束来执行几乎总是更好-unique index)。
使用下面的光标来禁用所有的约束..并改变查询启用约束…
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; /
看起来你不能用一个单一的命令来做到这一点,但是我可以find最接近它的地方。
这是禁用约束的另一种方法(它来自https://asktom.oracle.com/pls/asktom/f?p=100:11:2402577774283132::::P11_QUESTION_ID:399218963817 )
WITH qry0 AS (SELECT 'ALTER TABLE ' || child_tname || ' DISABLE CONSTRAINT ' || child_cons_name disable_fk , 'ALTER TABLE ' || parent_tname || ' DISABLE CONSTRAINT ' || parent.parent_cons_name disable_pk FROM (SELECT a.table_name child_tname ,a.constraint_name child_cons_name ,b.r_constraint_name parent_cons_name ,LISTAGG ( column_name, ',') WITHIN GROUP (ORDER BY position) child_columns FROM user_cons_columns a ,user_constraints b WHERE a.constraint_name = b.constraint_name AND b.constraint_type = 'R' GROUP BY a.table_name, a.constraint_name ,b.r_constraint_name) child ,(SELECT a.constraint_name parent_cons_name ,a.table_name parent_tname ,LISTAGG ( column_name, ',') WITHIN GROUP (ORDER BY position) parent_columns FROM user_cons_columns a ,user_constraints b WHERE a.constraint_name = b.constraint_name AND b.constraint_type IN ('P', 'U') GROUP BY a.table_name, a.constraint_name) parent WHERE child.parent_cons_name = parent.parent_cons_name AND (parent.parent_tname LIKE 'V2_%' OR child.child_tname LIKE 'V2_%')) SELECT DISTINCT disable_pk FROM qry0 UNION SELECT DISTINCT disable_fk FROM qry0;
奇迹般有效
在“禁用”脚本中,order by子句应该是:
ORDER BY c.constraint_type DESC, c.last_change DESC
本节的目标是按照正确的顺序禁用约束。
SELECT 'ALTER TABLE '||substr(c.table_name,1,35)|| ' DISABLE CONSTRAINT '||constraint_name||' ;' FROM user_constraints c, user_tables u WHERE c.table_name = u.table_name;
该语句返回closures所有约束(包括主键,外键和其他约束)的命令。