Отключить все ограничения таблиц в Oracle

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

Ответ 1

Лучше не записывать временные файлы спула. Используйте блок 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

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

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

Ответ 3

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

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

Ответ 4

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

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

Ответ 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;
/

Ответ 6

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

Ответ 7

В разделе "disable" script предложение order by должно выглядеть так:

ORDER BY c.constraint_type DESC, c.last_change DESC

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

Ответ 8

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; 

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

Ответ 9

Это еще один способ отключения ограничений (он пришел из 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;

работает как шарм