web-dev-qa-db-fra.com

Désactiver toutes les contraintes de table dans Oracle

Comment puis-je désactiver toutes les contraintes de table dans Oracle avec une seule commande?.

81
oneself

Il est préférable d'éviter d'écrire des fichiers de spool temporaires. Utilisez un bloc PL/SQL. Vous pouvez l'exécuter à partir de SQL * Plus ou l'insérer dans un package ou une procédure. La jointure à USER_TABLES est là pour éviter les contraintes de vue.

Il est peu probable que vous souhaitiez réellement désactiver toutes les contraintes (y compris NOT NULL, clés primaires, etc.). Vous devriez penser à mettre constraint_type dans la clause 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;
/

Réactiver les contraintes est un peu plus compliqué - vous devez activer les contraintes de clé primaire avant de pouvoir les référencer dans une contrainte de clé étrangère. Cela peut être fait en utilisant ORDER BY sur constraint_type. 'P' = clé primaire, 'R' = clé étrangère.

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;
/
129
WW.

Pour prendre en compte les dépendances entre les contraintes: 

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

Ce n'est pas une commande unique, mais voici comment je le fais. Le script suivant a été conçu pour s'exécuter en SQL * Plus. Remarque: j'ai volontairement écrit cela pour ne fonctionner que dans le schéma actuel.

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

Pour limiter ce que vous supprimez, filtrez une clause where dans l'instruction select: -

  • filtrez sur constraint_type pour ne supprimer que certains types de contraintes
  • filtrez sur nom_table pour ne le faire que pour une ou plusieurs tables.

Pour exécuter sur d'autres schémas que ceux du schéma actuel, modifiez l'instruction select afin qu'elle soit sélectionnée parmi toutes les contraintes plutôt que les contraintes utilisateur.

Remarque - pour une raison quelconque, je ne peux pas obtenir le soulignement de ne pas agir comme une italique dans le paragraphe précédent Si quelqu'un sait comment y remédier, n'hésitez pas à modifier cette réponse.

5
Mike McAllister

Utilisez le curseur suivant pour désactiver toutes les contraintes. Et modifiez la requête pour activer les contraintes ...

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

Cela peut être scripté en PL/SQL simplement en se basant sur la vue système DBA/ALL/USER_CONSTRAINTS, mais divers détails ne rendent pas aussi triviale que cela puisse paraître. Vous devez faire attention à l'ordre dans lequel cela est fait et vous devez également prendre en compte la présence d'index uniques.

La commande est importante car vous ne pouvez pas supprimer une clé unique ou primaire référencée par une clé étrangère, et il pourrait y avoir des clés étrangères sur des tables dans d'autres schémas faisant référence à des clés primaires dans votre propre ne peut pas laisser tomber ces PKs et UKs. De plus, vous ne pouvez pas transformer un index unique en index non unique. Vous devez donc le supprimer pour supprimer la contrainte (pour cette raison, il est presque toujours préférable d'implémenter des contraintes uniques en tant que contrainte "réelle" prise en charge par un non-contrainte. -unique index).

4
David Aldridge

Dans le script "disable", la clause order by devrait être la suivante:

ORDER BY c.constraint_type DESC, c.last_change DESC

Le but de cette clause est de désactiver les contraintes dans le bon ordre.

0
bpelhos

C'est une autre façon de désactiver les contraintes (cela vient de https://asktom.Oracle.com/pls/asktom/f?p=100:11:2402577774283132:::PP1_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;

fonctionne comme un charme

0
Cyryl1972

Vous pouvez exécuter toutes les commandes renvoyées par la requête suivante:

sélectionnez 'ALTER TABLE' || substr (nom_table, 1,35) || ' DISABLE CONSTRAINT '|| nom_contrainte ||' ; ' from user_constraints c -- où c.table_name = 'TABLE_NAME';

0
Cristina Bazar

Il ne semble pas que vous puissiez le faire avec une seule commande, mais ici ' est la chose la plus proche que j'ai pu trouver.

0
Adam Bellaire

avec curseur pour boucle (utilisateur = 'TRANEE', table = '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;
/

(Si vous modifiez Désactiver pour activer, vous pouvez activer toutes les contraintes.)

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

Cette instruction retourne les commandes qui désactivent toutes les contraintes, y compris la clé primaire, les clés étrangères et une autre contrainte.

0
Ankireddy Polu