Deshabilitar todas las restricciones de la tabla en Oracle

95

¿Cómo puedo deshabilitar todas las restricciones de tabla en Oracle con un solo comando? Esto puede ser para una sola tabla, una lista de tablas o para todas las tablas.

uno mismo
fuente

Respuestas:

147

Es mejor evitar escribir archivos de cola temporales. Utilice un bloque PL / SQL. Puede ejecutar esto desde SQL * Plus o ponerlo en un paquete o procedimiento. La unión a USER_TABLES está ahí para evitar restricciones de vista.

Es poco probable que realmente desee deshabilitar todas las restricciones (incluidas NOT NULL, claves primarias, etc.). Debería pensar en poner constraint_type en la cláusula 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;
/

Habilitar las restricciones de nuevo es un poco complicado: debe habilitar las restricciones de clave primaria antes de poder hacer referencia a ellas en una restricción de clave externa. Esto se puede hacer usando un ORDER BY en constraint_type. 'P' = clave primaria, 'R' = clave externa.

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;
/
WW.
fuente
2
¿Ese primer segmento de código no intentará deshabilitar las claves primarias antes de deshabilitar las claves externas?
David Aldridge
@David Creo que encontré este problema con el primer segmento. Lo resolví agregando 'DESC' entre 'ORDER BY c.constraint_type' y el cierre ')'
AndreiM
@WW Mi agradecimiento. Esto me ahorró la molestia de escribir una declaración SQL para generar las declaraciones de restricción Habilitar y Deshabilitar.
Dave
1
Las claves primarias no se pueden deshabilitar en tablas organizadas por índices. Puede manejarlos agregándolos AND NOT (t.iot_type IS NOT NULL AND c.constraint_type = 'P')al primer segmento de código.
Andrew Miller
2
Advertencia: si ya ha DESHABILITADO las restricciones, todas las restricciones se activarán utilizando ese procedimiento PL / SQL. Debe filtrar esas restricciones en el lugar para asegurarse de que se mantengan deshabilitadas.
nachouve
11

Para tener en cuenta las dependencias entre las restricciones:

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;
/
Cyryl1972
fuente
5

No es un solo comando, pero así es como lo hago. El siguiente script ha sido diseñado para ejecutarse en SQL * Plus. Tenga en cuenta que he escrito esto a propósito para que solo funcione dentro del esquema actual.

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

Para restringir lo que suelta, agregue un filtro donde la cláusula a la declaración de selección: -

  • filtrar por tipo de restricción para eliminar solo tipos particulares de restricciones
  • filtre en table_name para hacerlo solo para una o algunas tablas.

Para ejecutar en más del esquema actual, modifique la instrucción select para seleccionar de all_constraints en lugar de user_constraints.

Nota : por alguna razón, no puedo hacer que el guión bajo NO actúe como una cursiva en el párrafo anterior. Si alguien sabe cómo solucionarlo, no dude en editar esta respuesta.

Mike McAllister
fuente
Si desea DESHABILITAR las restricciones en lugar de DROPinglas, simplemente edite la declaración SELECT anterior: 'eliminar restricción' para leer 'deshabilitar restricción' HTH: o)
Andrew
Sí, es una buena sugerencia; en el futuro, siéntase libre de editar la publicación para agregar esta información. Es por eso que tengo mis publicaciones como wiki de la comunidad editables.
Mike McAllister
5

Utilice el cursor siguiente para deshabilitar todas las restricciones ... Y modifique la consulta para habilitar las restricciones ...

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;
/
user486360
fuente
4

Esto se puede escribir en PL / SQL de manera bastante simple basándose en la vista del sistema DBA / ALL / USER_CONSTRAINTS, pero varios detalles no lo hacen tan trivial como suena. Hay que tener cuidado con el orden en que se realiza y también hay que tener en cuenta la presencia de índices únicos.

El orden es importante porque no puede eliminar una clave única o primaria a la que hace referencia una clave externa, y podría haber claves externas en tablas en otros esquemas que hagan referencia a claves primarias en el suyo, por lo que a menos que tenga el privilegio ALTER ANY TABLE, entonces no se pueden eliminar esos PK y UK. Además, no puede cambiar un índice único para que sea un índice no único, por lo que debe eliminarlo para eliminar la restricción (por esta razón, casi siempre es mejor implementar restricciones únicas como una restricción "real" que es compatible con una restricción no -índice único).

David Aldridge
fuente
0

No parece que pueda hacer esto con un solo comando, pero esto es lo más parecido que pude encontrar.

Adam Bellaire
fuente
0

Esta es otra forma de deshabilitar las restricciones (provino 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;

Funciona de maravilla

Cyryl1972
fuente
0

En el script "deshabilitar", el orden por cláusula debe ser el siguiente:

ORDER BY c.constraint_type DESC, c.last_change DESC

El objetivo de esta cláusula es deshabilitar las restricciones en el orden correcto.

Cristian Chaparro A.
fuente
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; 

Esta declaración devuelve los comandos que desactivan todas las restricciones, incluida la clave principal, las claves externas y otras restricciones.

Ankireddy Polu
fuente
0

con cursor para bucle (usuario = 'TRANEE', tabla = '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 cambia deshabilitar a habilitar, puede habilitar todas las restricciones)

diafol
fuente
0

Puede ejecutar todos los comandos devueltos por la siguiente consulta:

seleccione 'ALTER TABLE' || substr (c.table_name, 1,35) || 'DESACTIVAR RESTRICCIÓN' || nombre_restricción || ' ; ' from user_constraints c --donde c.table_name = 'TABLE_NAME';

Cristina Bazar
fuente