Отключить все ограничения таблиц в Oracle - PullRequest
84 голосов
/ 24 сентября 2008

Как я могу отключить все ограничения таблиц в Oracle с помощью одной команды? Это может быть как для одной таблицы, списка таблиц, так и для всех таблиц.

Ответы [ 11 ]

133 голосов
/ 25 сентября 2008

Лучше избегать записи временных файлов спула. Используйте блок PL / SQL. Вы можете запустить это из SQL * Plus или поместить это в пакет или процедуру. Соединение с USER_TABLES позволяет избежать ограничений просмотра.

Маловероятно, что вы действительно хотите отключить все ограничения (включая NOT NULL, первичные ключи и т. Д.). Вам следует подумать о том, чтобы добавить тип_ограничения в предложении 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;
/
9 голосов
/ 22 февраля 2011

Чтобы учесть зависимости между ограничениями:

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 голосов
/ 25 октября 2010

Используйте следующий курсор, чтобы отключить все ограничения .. И измените запрос для включения ограничений ...

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;
/
5 голосов
/ 24 сентября 2008

Это не одна команда, но вот как я это делаю. Следующий скрипт был разработан для запуска в 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: -

  • фильтр по типу restint_type для удаления только определенных типов ограничений
  • Фильтр для table_name, чтобы сделать это только для одной или нескольких таблиц.

Чтобы выполнить больше, чем текущая схема, измените оператор select, чтобы выбрать из всех_констант, а не user_constraints.

Примечание - по какой-то причине я не могу получить подчеркивание, чтобы НЕ действовать как курсив в предыдущем абзаце. Если кто-то знает, как это исправить, отредактируйте этот ответ.

4 голосов
/ 24 сентября 2008

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

Порядок важен, потому что вы не можете удалить уникальный или первичный ключ, на который ссылается внешний ключ, и могут быть внешние ключи в таблицах в других схемах, которые ссылаются на первичные ключи в вашей собственной, поэтому, если у вас нет ALTER ANY TABLE привилегия, то вы не можете отказаться от этих PK и UK. Также вы не можете переключить уникальный индекс на неуникальный индекс, поэтому вы должны удалить его, чтобы удалить ограничение (по этой причине почти всегда лучше реализовывать уникальные ограничения как «реальное» ограничение, которое поддерживается не -уникальный индекс).

0 голосов
/ 24 октября 2018

Вы можете выполнить все команды, возвращаемые следующим запросом:

выберите «ALTER TABLE» || substr (c.table_name, 1,35) || 'DISABLE CONSTRAINT' || имя_связи || ' ;» из user_constraints c --where c.table_name = 'TABLE_NAME';

0 голосов
/ 04 июля 2018

с курсором для цикла (пользователь = 'TRANEE', таблица = '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 голосов
/ 27 октября 2016

Это еще один способ отключения ограничений (взято из 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 голосов
/ 06 февраля 2015
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 голосов
/ 09 июля 2009

В сценарии «отключить» предложение order by должно быть таким:

ORDER BY c.constraint_type DESC, c.last_change DESC

Цель этого пункта - отключить ограничения в правильном порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...