Oracleのすべてのテーブル制約を無効にする


95

Oracleのすべてのテーブル制約を1つのコマンドで無効にするにはどうすればよいですか?これは、単一のテーブル、テーブルのリスト、またはすべてのテーブルのいずれかです。

回答:


147

一時スプールファイルを書き出さないようにすることをお勧めします。PL / SQLブロックを使用します。これはSQL * Plusから実行することも、パッケージまたはプロシージャに入れることもできます。USER_TABLESへの結合は、ビューの制約を回避するためにあります。

すべての制約(NOT NULL、主キーなどを含む)を本当に無効にしたいとは思わないでしょう。WHERE句にconstraint_typeを配置することを検討する必要があります。

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

制約を再度有効にするのは少し注意が必要です。外部キー制約で主キー制約を参照するには、主キー制約を有効にする必要があります。これは、constraint_typeでORDER BYを使用して実行できます。「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 Aldridge

@David最初のセグメントでこの問題に遭遇したと思います。「ORDER BY c.constraint_type」とクロージング「)」の間に「DESC」を追加して解決しました
AndreiM

@WWありがとうございます。これにより、SQLステートメントを記述して、EnableおよびDisable制約ステートメントを生成する手間が省けました。
デイブ

1
索引構成表では主キーを無効化できません。これらAND NOT (t.iot_type IS NOT NULL AND c.constraint_type = 'P')は、最初のコードセグメントに追加することで処理できます。
Andrew Miller

2
警告:すでにDISABLED制約がある場合、そのPL / SQLプロシージャを使用してすべての制約がアクティブになります。制約を無効にしておく場所を制限する必要があります。
nachouve 2015年

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

ドロップするものを制限するには、selectステートメントにwhere句をフィルターで追加します。

  • 特定のタイプの制約のみを削除するために、constraint_typeでフィルタリングします
  • 1つまたはいくつかのテーブルに対してのみ行うには、table_nameでフィルタリングします。

現在のスキーマ以外で実行するには、selectステートメントを変更して、user_constraintsではなくall_constraintsから選択するようにします。

-何らかの理由で、前の段落でアンダースコアをイタリック体のように機能させることができません。誰かがそれを修正する方法を知っている場合は、この回答を自由に編集してください。


あなたがそれらをDROPingのではなく、制約を無効にしたい場合は、単純にSELECT文の上で編集:「ドロップ制約」読み込むための「ディセーブル制約」HTH:O)
アンドリュー・

はい、それは良い提案です。将来的には、この情報を追加するために投稿を自由に編集してください。そのため、コミュニティWikiとして投稿を編集できます。
マイクマカリスター

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

これは、DBA / ALL / USER_CONSTRAINTSシステムビューに基づいてPL / SQLで簡単にスクリプト化できますが、さまざまな詳細は、思ったほど簡単ではありません。実行される順序に注意する必要があり、一意のインデックスの存在も考慮する必要があります。

外部キーによって参照される一意のキーまたは主キーを削除することはできず、独自の主キーを参照する他のスキーマのテーブルに外部キーが存在する可能性があるため、順序は重要です。したがって、ALTER ANY TABLE権限がないと、それらのPKとUKをドロップすることはできません。また、一意のインデックスを非一意のインデックスに切り替えることはできないため、制約を削除するためにそれを削除する必要があります(このため、ほとんどの場合、一意の制約を非実際にサポートされている「実際の」制約として実装する方が優れています-一意のインデックス)。



0

これは、制約を無効にするもう1つの方法です(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

"disable"スクリプトでは、order by句は次のようになります。

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

カーソルforループあり(ユーザー= '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

次のクエリで返されるすべてのコマンドを実行できます。

'ALTER TABLE' || substr(c.table_name、1,35)||を選択します '制約を無効にする' || constraint_name || ' ; ' from user_constraints c --where c.table_name = 'TABLE_NAME';

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.