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.
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.
Respostas:
É 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;
/
AND NOT (t.iot_type IS NOT NULL AND c.constraint_type = 'P')ao primeiro segmento de código.
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;
/
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: -
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.
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;
/
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).
Parece que você não pode fazer isso com um único comando, mas aqui está a coisa mais próxima que pude encontrar.
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
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.
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.
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)
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';