禁用Oracle中的所有表约束


95

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

Answers:


147

最好避免写出临时假脱机文件。使用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;
/

2
在禁用外键之前,第一个代码段不是要尝试禁用主键吗?
David Aldridge

@David我想我在第一部分遇到了这个问题。我通过在“ ORDER BY c.constraint_type”和结束

@WW非常感谢。这为我省去了编写SQL语句以生成Enable和Disable约束语句的麻烦。
戴夫

1
无法在索引组织的表上禁用主键。您可以通过添加AND NOT (t.iot_type IS NOT NULL AND c.constraint_type = 'P')到第一个代码段来处理这些问题。
安德鲁·米勒

2
警告:如果您已经禁用了约束,则将使用该PL / SQL过程激活所有约束。您必须在哪里过滤那些约束,以确保它们保持禁用状态。
nachouve

11

要计算约束之间的依赖关系:

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;
/

5

这不是一个命令,但这是我的操作方法。下面的脚本被设计为可以在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进行过滤以仅删除特定类型的约束
  • 对table_name进行过滤以仅对一个或几个表执行此操作。

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

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


如果要禁用约束而不是丢弃约束,则只需编辑上面的SELECT语句:'drop Constraint'读取为'disable Constraint'HTH:o)
Andrew

是的,这是一个好建议-以后,随时可以编辑帖子以添加此信息。这就是为什么我的帖子可以作为社区Wiki进行编辑的原因。
Mike McAllister

5

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

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;
/

4

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

该顺序很重要,因为您不能删除由外键引用的唯一键或主键,并且在其他模式中的表上可能会有外键引用您自己的主键,因此除非您拥有ALTER ANY TABLE特权,否则您必须无法删除这些PK和UK。另外,您不能将唯一索引切换为非唯一索引,因此必须删除它才能删除约束(因此,将唯一约束实现为非约束支持的“真实”约束几乎总是更好的选择) -唯一索引)。



0

这是禁用约束的另一种方式(它来自 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;

奇迹般有效


0

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

ORDER BY c.constraint_type DESC, c.last_change DESC

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


0
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; 

该语句返回关闭所有约束(包括主键,外键和其他约束)的命令。


0

使用游标进行循环(用户='TRANEE',表='D')

declare
    constr all_constraints.constraint_name%TYPE;
begin
    for constr in
        (select constraint_name from all_constraints
        where table_name = 'D'
        and owner = 'TRANEE')
    loop
        execute immediate 'alter table D disable constraint '||constr.constraint_name;
    end loop;
end;
/

(如果将禁用更改为启用,则可以使所有约束都启用)


0

您可以执行以下查询返回的所有命令:

选择'ALTER TABLE'|| substr(c.table_name,1,35)|| 'DISABLE CONSTRAINT'|| constraint_name ||' ;' 来自user_constraints c-其中c.table_name ='TABLE_NAME';

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.