Nonaktifkan semua batasan tabel di Oracle

96

Bagaimana cara menonaktifkan semua batasan tabel di Oracle dengan satu perintah? Ini bisa untuk satu tabel, daftar tabel, atau untuk semua tabel.

diri
sumber

Jawaban:

148

Lebih baik hindari menulis file spool sementara. Gunakan blok PL / SQL. Anda dapat menjalankan ini dari SQL * Plus atau memasukkannya ke dalam paket atau prosedur. Gabungan ke USER_TABLES dilakukan untuk menghindari batasan tampilan.

Tidak mungkin Anda benar-benar ingin menonaktifkan semua batasan (termasuk NOT NULL, kunci primer, dll). Anda harus berpikir untuk meletakkan constraint_type di klausa 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;
/

Mengaktifkan batasan lagi sedikit lebih rumit - Anda perlu mengaktifkan batasan kunci utama sebelum Anda dapat mereferensikannya dalam batasan kunci asing. Ini dapat dilakukan menggunakan ORDER BY pada constraint_type. 'P' = kunci primer, 'R' = kunci asing.

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;
/
WW.
sumber
2
Bukankah segmen kode pertama itu akan mencoba menonaktifkan kunci utama sebelum menonaktifkan kunci asing?
David Aldridge
@David Sepertinya saya mengalami masalah ini dengan segmen pertama. Saya menyelesaikannya dengan menambahkan 'DESC' antara 'ORDER BY c.constraint_type' dan penutup ')'
AndreiM
@WW Apresiasi saya. Ini hanya menyelamatkan saya dari masalah menulis pernyataan SQL untuk menghasilkan pernyataan kendala Aktifkan dan Nonaktifkan.
Dave
1
Kunci utama tidak dapat dinonaktifkan pada tabel yang diatur indeks. Anda dapat menangani ini dengan menambahkan AND NOT (t.iot_type IS NOT NULL AND c.constraint_type = 'P')ke segmen kode pertama.
Andrew Miller
2
Peringatan: jika Anda telah DISABLED contraint, semua batasan akan diaktifkan dengan menggunakan prosedur PL / SQL. Anda harus memfilter pembatas tersebut di mana untuk memastikannya tetap dinonaktifkan.
nachouve
11

Untuk memperhitungkan dependensi antara batasan:

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;
/
Cyryl1972
sumber
5

Ini bukan perintah tunggal, tapi begini cara saya melakukannya. Skrip berikut telah dirancang untuk berjalan di SQL * Plus. Catatan, saya sengaja menulis ini hanya untuk bekerja dalam skema saat ini.

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

Untuk membatasi apa yang Anda lepaskan, filter tambahkan klausa where ke pernyataan pilih: -

  • filter pada constraint_type untuk melepaskan tipe batasan tertentu saja
  • filter pada nama_tabel untuk melakukannya hanya untuk satu atau beberapa tabel.

Untuk berjalan di lebih dari skema saat ini, ubah pernyataan pilih untuk memilih dari all_constraints daripada user_constraints.

Catatan - untuk beberapa alasan saya tidak bisa membuat garis bawah TIDAK bertindak seperti huruf miring di paragraf sebelumnya. Jika seseorang tahu cara memperbaikinya, silakan edit jawaban ini.

Mike McAllister
sumber
Jika Anda ingin MENONAKTIFKAN batasan alih-alih MENARIKnya, cukup edit pernyataan SELECT di atas: 'jatuhkan batasan' untuk membaca 'nonaktifkan batasan' HTH: o)
Andrew
Ya, itu saran yang bagus - di masa mendatang, silakan edit postingan untuk menambahkan informasi ini. Itu sebabnya saya memiliki posting saya sebagai wiki komunitas yang dapat diedit.
Mike McAllister
5

Gunakan kursor berikut untuk menonaktifkan semua kendala .. Dan mengubah kueri untuk mengaktifkan kendala ...

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;
/
pengguna486360
sumber
4

Ini dapat ditulis dalam PL / SQL cukup sederhana berdasarkan tampilan sistem DBA / ALL / USER_CONSTRAINTS, tetapi berbagai detail membuatnya tidak sepele kedengarannya. Anda harus berhati-hati tentang urutan pelaksanaannya dan Anda juga harus memperhitungkan keberadaan indeks unik.

Urutan ini penting karena Anda tidak dapat menjatuhkan kunci unik atau primer yang direferensikan oleh kunci asing, dan mungkin ada kunci asing pada tabel di skema lain yang mereferensikan kunci primer di Anda sendiri, jadi kecuali Anda memiliki hak istimewa ALTER ANY TABLE maka Anda tidak bisa menjatuhkan PK dan UK itu. Anda juga tidak dapat mengubah indeks unik menjadi indeks non-unik sehingga Anda harus melepaskannya untuk menghilangkan batasan (karena alasan ini, hampir selalu lebih baik untuk menerapkan batasan unik sebagai batasan "nyata" yang didukung oleh non -indeks unik).

David Aldridge
sumber
0

Sepertinya Anda tidak dapat melakukan ini dengan satu perintah, tetapi inilah hal terdekat yang dapat saya temukan.

Adam Bellaire
sumber
0

Ini adalah cara lain untuk menonaktifkan kendala (berasal dari 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;

bekerja seperti pesona

Cyryl1972
sumber
0

Dalam skrip "nonaktifkan", urutan menurut klausa harus seperti ini:

ORDER BY c.constraint_type DESC, c.last_change DESC

Tujuan dari klausa ini adalah menonaktifkan batasan dalam urutan yang benar.

Cristian Chaparro A.
sumber
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; 

Pernyataan ini mengembalikan perintah yang mematikan semua batasan termasuk kunci utama, kunci asing, dan batasan lain.

Ankireddy Polu
sumber
0

dengan kursor untuk loop (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;
/

(Jika Anda mengubah nonaktifkan untuk mengaktifkan, Anda dapat mengaktifkan semua batasan)

diafol
sumber
0

Anda dapat menjalankan semua perintah yang dikembalikan oleh kueri berikut:

pilih 'ALTER TABLE' || substr (c.table_name, 1,35) || 'DISABLE CONSTRAINT' || constraint_name || ' ; ' dari user_constraints c --dimana c.table_name = 'TABLE_NAME';

Cristina Bazar
sumber