Desative todas as restrições de tabela no Oracle

95

Como posso desabilitar todas as restrições de tabela no Oracle com um único comando? Isso pode ser para uma única tabela, uma lista de tabelas ou para todas as tabelas.

a si mesmo
fonte

Respostas:

147

É melhor evitar a gravação de arquivos de spool temporários. Use um bloco PL / SQL. Você pode executá-lo no SQL * Plus ou colocá-lo em um pacote ou procedimento. A junção com USER_TABLES existe para evitar restrições de visualização.

É improvável que você realmente queira desabilitar todas as restrições (incluindo NOT NULL, chaves primárias, etc). Você deve pensar em colocar constraint_type na 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 as restrições novamente é um pouco mais complicado - você precisa habilitar as restrições de chave primária antes de fazer referência a elas em uma restrição de chave estrangeira. Isso pode ser feito usando um ORDER BY em constraint_type. 'P' = chave primária, 'R' = chave estrangeira.

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.
fonte
2
Esse primeiro segmento de código não tentará desabilitar as chaves primárias antes de desabilitar as chaves estrangeiras?
David Aldridge,
@David Acho que tive esse problema com o primeiro segmento. Resolvi isso adicionando 'DESC' entre 'ORDER BY c.constraint_type' e o fechamento ')'
AndreiM
@WW Meu agradecimento. Isso apenas me poupou do trabalho de escrever uma instrução SQL para gerar as instruções de restrição Enable e Disable.
dave de
1
As chaves primárias não podem ser desabilitadas em tabelas organizadas por índice. Você pode lidar com isso adicionando AND NOT (t.iot_type IS NOT NULL AND c.constraint_type = 'P')ao primeiro segmento de código.
Andrew Miller
2
Atenção: se você já DISABLED as restrições, todas as restrições serão ativadas usando esse procedimento PL / SQL. Você tem que filtrar essas restrições sobre o local para garantir que continuem desativadas.
nachouve
11

Para levar em conta as dependências entre as restrições:

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
fonte
5

Não é um único comando, mas é assim que o faço. O seguinte script foi desenvolvido para ser executado no SQL * Plus. Observe, eu escrevi isso propositalmente para funcionar apenas dentro do esquema atual.

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 o que você solta, filtre e adicione uma cláusula where à instrução select: -

  • filtre constraint_type para descartar apenas determinados tipos de restrições
  • filtrar em nome_tabela para fazê-lo apenas para uma ou algumas tabelas.

Para executar em mais do que o esquema atual, modifique a instrução select para selecionar all_constraints em vez de user_constraints.

Observação - por algum motivo, não consigo fazer o sublinhado NÃO agir como um itálico no parágrafo anterior. Se alguém souber como consertar, sinta-se à vontade para editar esta resposta.

Mike McAllister
fonte
Se você quiser DESABILITAR as restrições em vez de DROP, simplesmente edite a instrução SELECT acima: 'drop constraint' para ler 'desabilitar restrição' HTH: o)
Andrew,
Sim, é uma boa sugestão - no futuro, sinta-se à vontade para editar a postagem e adicionar essas informações. É por isso que tenho minhas postagens editáveis ​​no wiki da comunidade.
Mike McAllister,
5

Use o seguinte cursor para desativar todas as restrições. E altere a consulta para ativar as restrições ...

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
fonte
4

Isso pode ser programado em PL / SQL de forma bastante simples com base na visão do sistema DBA / ALL / USER_CONSTRAINTS, mas vários detalhes não são tão triviais quanto parece. Você deve ter cuidado com a ordem em que isso é feito e também levar em consideração a presença de índices exclusivos.

A ordem é importante porque você não pode descartar uma chave única ou primária que é referenciada por uma chave estrangeira, e pode haver chaves estrangeiras em tabelas em outros esquemas que fazem referência a chaves primárias em seu próprio, então a menos que você tenha o privilégio ALTER ANY TABLE, então você não pode descartar esses PKs e UKs. Além disso, você não pode mudar um índice único para um índice não único, então você tem que eliminá-lo para eliminar a restrição (por esta razão, é quase sempre melhor implementar restrições únicas como uma restrição "real" que é suportada por uma restrição - índice único).

David Aldridge
fonte
0

Parece que você não pode fazer isso com um único comando, mas aqui está a coisa mais próxima que pude encontrar.

Adam Bellaire
fonte
0

Esta é outra maneira de desabilitar restrições (veio 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 como um encanto

Cyryl1972
fonte
0

No script "desabilitar", a cláusula order by deve ser esta:

ORDER BY c.constraint_type DESC, c.last_change DESC

O objetivo desta cláusula é desativar as restrições na ordem certa.

Cristian Chaparro A.
fonte
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 instrução retorna os comandos que desligam todas as restrições, incluindo chave primária, chaves estrangeiras e outras restrições.

Ankireddy Polu
fonte
0

com cursor para loop (usuário = 'TRANEE', tabela = '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;
/

(Se você alterar desativar para ativar, poderá tornar todas as restrições ativadas)

diafol
fonte
0

Você pode executar todos os comandos retornados pela seguinte consulta:

selecione 'ALTER TABLE' || substr (c.table_name, 1,35) || 'DISABLE CONSTRAINT' || constraint_name || ' ; ' from user_constraints c --onde c.table_name = 'TABLE_NAME';

Cristina Bazar
fonte