Вимкніть усі обмеження таблиці в Oracle


95

Як я можу відключити всі обмеження таблиці в Oracle за допомогою однієї команди? Це може бути як для однієї таблиці, списку таблиць, так і для всіх таблиць.

Відповіді:


147

Краще уникати виписування тимчасових шпульних файлів. Використовуйте блок PL / SQL. Ви можете запустити це з SQL * Plus або помістити цю річ у пакет або процедуру. Приєднання до USER_TABLES існує, щоб уникнути обмежень перегляду.

Навряд чи ви дійсно хочете відключити всі обмеження (включаючи NOT NULL, первинні ключі тощо). Вам слід подумати про введення constraint_type у речення 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;
/

Повторне ввімкнення обмежень трохи хитріше - вам потрібно ввімкнути обмеження первинного ключа, перш ніж ви зможете посилатися на них у обмеженні зовнішнього ключа. Це можна зробити за допомогою ORDER BY на constraint_type. 'P' = первинний ключ, 'R' = зовнішній ключ.

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
Хіба цей перший сегмент коду не намагатиметься відключити первинні ключі до того, як він вимкне зовнішні ключі?
Девід Олдрідж

@David Я думаю, що наткнувся на це питання з першим сегментом. Я вирішив це, додавши 'DESC' між 'ORDER BY c.constraint_type' та закриттям ')'
AndreiM

@WW Моя вдячність. Це просто врятувало мене від проблеми написання оператора SQL для створення операторів обмеження Увімкнути та Вимкнути.
Дейв

1
Первинні ключі не можна вимкнути в таблицях, організованих за індексом. Ви можете впоратися з ними, додавши AND NOT (t.iot_type IS NOT NULL AND c.constraint_type = 'P')до першого сегменту коду.
Ендрю Міллер

2
Попередження: якщо у вас вже є ВІДМІНЕНІ контранти, усі обмеження будуть активовані за допомогою цієї процедури PL / SQL. Вам доведеться відфільтрувати ці контранти за тим, де вони будуть відключені.
nachouve

11

Щоб врахувати залежності між обмеженнями:

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

Це не одна команда, але ось як я це роблю. Наступний сценарій розроблений для роботи в SQL * Plus. Зауважте, я навмисно написав це, щоб працювати лише в рамках поточної схеми.

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

Щоб обмежити те, що ви втрачаєте, фільтр додайте пропозицію where до оператора select: -

  • фільтр для constraint_type, щоб скинути лише певні типи обмежень
  • фільтр на ім'я таблиці, щоб зробити це лише для однієї або кількох таблиць.

Щоб запустити більше, ніж поточна схема, змініть оператор select, щоб вибрати з all_constraints, а не user_constraints.

Примітка - з якихось причин я не можу отримати підкреслення, щоб НЕ діяти як курсив у попередньому параграфі. Якщо хтось знає, як це виправити, будь ласка, відредагуйте цю відповідь.


Якщо ви хочете ВИМКНУТИ обмеження замість ПАДАННЯ їх, просто відредагуйте наведене вище твердження SELECT: 'drop constraint', щоб прочитати 'відключити обмеження' HTH: o)
Ендрю

Так, це гарна порада - надалі сміливо редагуйте публікацію, щоб додати цю інформацію. Ось чому мої дописи у вікі спільноти можна редагувати.
Mike McAllister

5

Використовуйте наступний курсор, щоб вимкнути всі обмеження .. І змінити запит на включення обмежень ...

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

Це може бути написано на PL / SQL досить просто на основі перегляду системи DBA / ALL / USER_CONSTRAINTS, але різні деталі роблять не такими тривіальними, як це звучить. Ви повинні бути обережними щодо порядку, в якому це робиться, і ви також повинні враховувати наявність унікальних індексів.

Порядок важливий, оскільки ви не можете скинути унікальний або первинний ключ, на який посилається зовнішній ключ, і в таблицях в інших схемах, які посилаються на первинні ключі у вашому, можуть бути зовнішні ключі, тому, якщо у вас немає привілею ALTER LY TABLE, тоді ви не може відмовитись від цих ПК та Великобританії. Крім того, ви не можете переключити унікальний індекс на неідентичний індекс, тому вам доведеться скинути його, щоб скинути обмеження (з цієї причини майже завжди краще реалізовувати унікальні обмеження як "реальне" обмеження, яке підтримується не -унікальний індекс).


0

Не схоже, що ви можете зробити це за допомогою однієї команди, але ось найближче до неї, що я міг знайти.


0

Це ще один спосіб відключення обмежень (він надійшов з 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;

працює як шарм


0

У сценарії "вимкнення" порядок за пунктом повинен бути таким:

ORDER BY c.constraint_type DESC, c.last_change DESC

Метою цього пункту є вимкнення обмежень у правильному порядку.


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; 

Цей оператор повертає команди, які вимикають усі обмеження, включаючи первинний ключ, зовнішні ключі та інші обмеження.


0

з курсором для циклу (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;
/

(Якщо змінити деактивувати, щоб увімкнути, можна ввімкнути всі обмеження)


0

Ви можете виконати всі команди, повернуті за таким запитом:

виберіть 'ALTER TABLE' || підстроку (c.table_name, 1,35) || 'ВІМКНУТИ ОБМЕЖЕННЯ' || ім'я обмеження || ' ; ' від user_constraints c - where c.table_name = 'TABLE_NAME';

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.