Disabilita tutti i vincoli di tabella in Oracle


96

Come posso disabilitare tutti i vincoli di tabella in Oracle con un singolo comando? Può essere per una singola tabella, un elenco di tabelle o per tutte le tabelle.

Risposte:


148

È meglio evitare di scrivere file di spool temporanei. Usa un blocco PL / SQL. Puoi eseguirlo da SQL * Plus o inserirlo in un pacchetto o in una procedura. L'unione a USER_TABLES serve per evitare vincoli di visualizzazione.

È improbabile che tu voglia davvero disabilitare tutti i vincoli (inclusi NOT NULL, chiavi primarie, ecc.). Dovresti pensare di inserire constraint_type nella clausola 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;
/

Abilitare nuovamente i vincoli è un po 'più complicato: è necessario abilitare i vincoli della chiave primaria prima di poterli fare riferimento in un vincolo di chiave esterna. Questo può essere fatto usando un ORDER BY su constraint_type. "P" = chiave primaria, "R" = chiave esterna.

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

2
Quel primo segmento di codice non proverà a disabilitare le chiavi primarie prima di disabilitare le chiavi esterne?
David Aldridge,

@David Penso di aver riscontrato questo problema con il primo segmento. L'ho risolto aggiungendo 'DESC' tra 'ORDER BY c.constraint_type' e la chiusura ')'
AndreiM

@WW Il mio apprezzamento. Questo mi ha solo risparmiato la fatica di scrivere un'istruzione SQL per generare le istruzioni di vincolo Enable e Disable.
dave

1
Le chiavi primarie non possono essere disabilitate nelle tabelle organizzate per indice. Puoi gestirli aggiungendo AND NOT (t.iot_type IS NOT NULL AND c.constraint_type = 'P')al primo segmento di codice.
Andrew Miller

2
Attenzione: se hai già dei vincoli DISABILITATI, tutti i vincoli verranno attivati ​​utilizzando quella procedura PL / SQL. Devi filtrare quei limiti su dove assicurarti che rimangano disabilitati.
nachouve

11

Per tenere conto delle dipendenze tra i vincoli:

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

5

Non è un singolo comando, ma ecco come lo faccio. Il seguente script è stato progettato per essere eseguito in SQL * Plus. Nota, l'ho scritto appositamente per funzionare solo all'interno dello schema corrente.

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

Per limitare ciò che si rilascia, il filtro aggiunge una clausola where all'istruzione select: -

  • filtra su constraint_type per eliminare solo particolari tipi di vincoli
  • filtro su nome_tabella per farlo solo per una o poche tabelle.

Per eseguire più dello schema corrente, modificare l'istruzione select per selezionare da all_constraints anziché user_constraints.

Nota : per qualche motivo non riesco a far sì che il trattino basso NON si comporti come un corsivo nel paragrafo precedente. Se qualcuno sa come risolverlo, non esitare a modificare questa risposta.


Se si desidera DISABILITARE i vincoli invece di ELIMINARLI, è sufficiente modificare l'istruzione SELECT sopra: 'elimina vincolo' per leggere 'disabilita vincolo' HTH: o)
Andrew

Sì, è un buon suggerimento: in futuro, sentiti libero di modificare il post per aggiungere queste informazioni. Ecco perché ho i miei post come wiki della comunità modificabili.
Mike McAllister,

5

Usa il seguente cursore per disabilitare tutti i vincoli .. E modifica la query per abilitare i vincoli ...

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

4

Questo può essere scritto in PL / SQL abbastanza semplicemente sulla base della vista di sistema DBA / ALL / USER_CONSTRAINTS, ma vari dettagli rendono non così banale come sembra. Devi stare attento all'ordine in cui viene fatto e devi anche tenere conto della presenza di indici univoci.

L'ordine è importante perché non puoi eliminare una chiave univoca o primaria a cui fa riferimento una chiave esterna e potrebbero esserci chiavi esterne su tabelle in altri schemi che fanno riferimento a chiavi primarie nel tuo, quindi a meno che tu non abbia il privilegio ALTER ANY TABLE allora tu non può abbandonare quei PK e UK. Inoltre non puoi cambiare un indice univoco in un indice non univoco quindi devi rilasciarlo per eliminare il vincolo (per questo motivo è quasi sempre meglio implementare vincoli univoci come vincoli "reali" supportati da un non -indice unico).


0

Non sembra che tu possa farlo con un solo comando, ma ecco la cosa più vicina che sono riuscito a trovare.


0

Questo è un altro modo per disabilitare i vincoli (proviene da 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;

funziona come un fascino


0

Nello script "disable", la clausola order by dovrebbe essere quella:

ORDER BY c.constraint_type DESC, c.last_change DESC

L'obiettivo di questa clausola è disabilitare i vincoli nell'ordine corretto.


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; 

Questa istruzione restituisce i comandi che disattivano tutti i vincoli, inclusa la chiave primaria, le chiavi esterne e altri vincoli.


0

con cursore per ciclo (utente = 'TRANEE', tabella = '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 cambi disabilita in abilita, puoi abilitare tutti i vincoli)


0

È possibile eseguire tutti i comandi restituiti dalla seguente query:

seleziona "ALTER TABLE" || substr (c.table_name, 1,35) || "DISABILITA VINCOLO" || nome_vincolo || " ; ' da user_constraints c - dove c.table_name = 'TABLE_NAME';

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.