Deaktivieren Sie alle Tabelleneinschränkungen in Oracle


95

Wie kann ich alle Tabelleneinschränkungen in Oracle mit einem einzigen Befehl deaktivieren? Dies kann entweder für eine einzelne Tabelle, eine Liste von Tabellen oder für alle Tabellen erfolgen.

Antworten:


147

Es ist besser zu vermeiden, temporäre Spooldateien zu schreiben. Verwenden Sie einen PL / SQL-Block. Sie können dies in SQL * Plus ausführen oder dieses Ding in ein Paket oder eine Prozedur einfügen. Der Join zu USER_TABLES dient dazu, Ansichtsbeschränkungen zu vermeiden.

Es ist unwahrscheinlich, dass Sie wirklich alle Einschränkungen deaktivieren möchten (einschließlich NOT NULL, Primärschlüssel usw.). Sie sollten darüber nachdenken, Constraint_Type in die WHERE-Klausel aufzunehmen.

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

Das erneute Aktivieren der Einschränkungen ist etwas schwierig. Sie müssen die Primärschlüsseleinschränkungen aktivieren, bevor Sie sie in einer Fremdschlüsseleinschränkung referenzieren können. Dies kann mit einem ORDER BY für Constraint_Type erfolgen. 'P' = Primärschlüssel, 'R' = Fremdschlüssel.

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
Wird dieses erste Codesegment nicht versuchen, Primärschlüssel zu deaktivieren, bevor Fremdschlüssel deaktiviert werden?
David Aldridge

@ David Ich glaube, ich bin mit dem ersten Segment auf dieses Problem gestoßen. Ich habe es gelöst, indem ich 'DESC' zwischen 'ORDER BY c.constraint_type' und dem abschließenden ')'
hinzugefügt habe

@WW Meine Wertschätzung. Dies ersparte mir nur die Mühe, eine SQL-Anweisung zum Generieren der Enable- und Disable-Einschränkungsanweisungen zu schreiben.
Dave

1
Primärschlüssel können für indexorganisierte Tabellen nicht deaktiviert werden. Sie können damit umgehen, indem Sie AND NOT (t.iot_type IS NOT NULL AND c.constraint_type = 'P')dem ersten Codesegment hinzufügen .
Andrew Miller

2
Warnung: Wenn Sie bereits Einschränkungen deaktiviert haben, werden alle Einschränkungen mithilfe dieser PL / SQL-Prozedur aktiviert. Sie müssen diese Einschränkungen nach dem Ort filtern, um sicherzustellen, dass sie deaktiviert bleiben.
Nachouve

11

So berücksichtigen Sie die Abhängigkeiten zwischen den Einschränkungen:

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

Es ist kein einzelner Befehl, aber so mache ich es. Das folgende Skript wurde für die Ausführung in SQL * Plus entwickelt. Beachten Sie, dass ich dies absichtlich so geschrieben habe, dass es nur innerhalb des aktuellen Schemas funktioniert.

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

Um einzuschränken, was Sie löschen, fügen Sie der select-Anweisung eine where-Klausel hinzu: -

  • Filtern Sie nach Constraint_Type, um nur bestimmte Arten von Constraints zu löschen
  • Filtern Sie nach Tabellenname, um dies nur für eine oder mehrere Tabellen zu tun.

Um mehr als das aktuelle Schema auszuführen, ändern Sie die select-Anweisung so, dass sie aus all_constraints und nicht aus user_constraints ausgewählt wird.

Hinweis - Aus irgendeinem Grund kann ich den Unterstrich nicht dazu bringen, sich NICHT wie eine Kursivschrift im vorherigen Absatz zu verhalten. Wenn jemand weiß, wie man das Problem behebt, können Sie diese Antwort jederzeit bearbeiten.


Wenn Sie die Einschränkungen deaktivieren möchten, anstatt sie zu löschen, bearbeiten Sie einfach die obige SELECT-Anweisung: 'Einschränkung löschen', um 'Einschränkung deaktivieren' zu lesen. HTH: o)
Andrew

Ja, das ist ein guter Vorschlag. In Zukunft können Sie den Beitrag bearbeiten, um diese Informationen hinzuzufügen. Deshalb kann ich meine Beiträge als Community-Wiki bearbeiten.
Mike McAllister

5

Verwenden Sie den folgenden Cursor, um alle Einschränkungen zu deaktivieren. Ändern Sie die Abfrage, um Einschränkungen zu aktivieren.

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

Dies kann in PL / SQL ziemlich einfach basierend auf der Systemansicht DBA / ALL / USER_CONSTRAINTS geschrieben werden, aber verschiedene Details sind nicht so trivial, wie es sich anhört. Sie müssen vorsichtig mit der Reihenfolge sein, in der es durchgeführt wird, und Sie müssen auch das Vorhandensein eindeutiger Indizes berücksichtigen.

Die Reihenfolge ist wichtig, da Sie keinen eindeutigen oder Primärschlüssel löschen können, auf den von einem Fremdschlüssel verwiesen wird, und es möglicherweise Fremdschlüssel in Tabellen in anderen Schemas gibt, die auf Primärschlüssel in Ihren eigenen verweisen Diese PKs und UKs können nicht gelöscht werden. Sie können einen eindeutigen Index auch nicht in einen nicht eindeutigen Index umwandeln, sodass Sie ihn löschen müssen, um die Einschränkung zu löschen (aus diesem Grund ist es fast immer besser, eindeutige Einschränkungen als "echte" Einschränkung zu implementieren, die von einem Nicht-Index unterstützt wird -eindeutiger Index).


0

Es sieht nicht so aus, als könnten Sie dies mit einem einzigen Befehl tun, aber hier ist das Nächste, was ich finden könnte.


0

Dies ist eine weitere Möglichkeit zum Deaktivieren von Einschränkungen (von 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;

klappt wunderbar


0

Im "disable" -Skript sollte die Reihenfolge nach Klausel lauten:

ORDER BY c.constraint_type DESC, c.last_change DESC

Das Ziel dieser Klausel ist es, die Einschränkungen in der richtigen Reihenfolge zu deaktivieren.


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; 

Diese Anweisung gibt die Befehle zurück, mit denen alle Einschränkungen deaktiviert werden, einschließlich Primärschlüssel, Fremdschlüssel und andere Einschränkungen.


0

mit Cursor für Schleife (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;
/

(Wenn Sie Deaktivieren in Aktivieren ändern, können Sie alle Einschränkungen aktivieren.)


0

Sie können alle von der folgenden Abfrage zurückgegebenen Befehle ausführen:

Wählen Sie 'ALTER TABLE' || substr (c.table_name, 1,35) || 'DISABLE CONSTRAINT' || Constraint_Name || ' ; ' from user_constraints c --where c.table_name = 'TABLE_NAME';

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.