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? Cela peut être soit pour une seule table, une liste de tables, soit pour toutes les tables.

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

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

Activer à nouveau les contraintes est un peu 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 un 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; / 

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

Ce n’est pas une commande unique, mais voici comment je le fais. Le script suivant a été conçu pour s’exécuter dans SQL * Plus. Notez que j’ai volontairement écrit ceci 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 déposez, filtrez une clause where dans l’instruction select: –

  • filtre sur constraint_type pour ne supprimer que certains types de contraintes
  • filtrer sur nom_table pour le faire uniquement pour une ou quelques tables.

Pour exécuter plus que le schéma actuel, modifiez l’instruction select pour sélectionner parmi all_constraints plutôt que user_constraints.

Remarque – pour une raison quelconque, je ne peux pas obtenir que le trait de soulignement n’agisse comme une italique dans le paragraphe précédent. Si quelqu’un sait comment résoudre ce problème, n’hésitez pas à modifier cette réponse.

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

Cela peut être scripté en PL / SQL plutôt simplement en fonction de la vue système DBA / ALL / USER_CONSTRAINTS, mais divers détails ne sont pas aussi sortingviaux que cela puisse paraître. Vous devez faire attention à l’ordre dans lequel vous le faites et vous devez également tenir compte de la présence d’index uniques.

L’ordre est important car vous ne pouvez pas supprimer une clé unique ou primaire référencée par une clé étrangère, et il peut y avoir des clés étrangères dans les tables d’autres schémas référençant des clés primaires dans votre propre système. ne peut pas laisser tomber ces PK et UKs. De plus, vous ne pouvez pas changer un index unique en un index non unique, vous devez donc le déposer pour supprimer la contrainte (pour cette raison, il est presque toujours préférable d’implémenter des contraintes uniques comme une contrainte “réelle” prise en charge par un non -unique index).

Il ne semble pas que vous puissiez faire cela avec une seule commande, mais voici la chose la plus proche que je pourrais trouver.

Ceci est un autre moyen de désactiver les contraintes (il vient de 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; 

fonctionne comme un charme

Dans le script “disable”, la clause order by doit ê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.

 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 renvoie les commandes qui désactivent toutes les contraintes, y compris la clé primaire, les clés étrangères et d’autres contraintes.

avec curseur pour la boucle (user = ‘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)