Bagaimana cara menonaktifkan semua batasan tabel di Oracle dengan satu perintah? Ini bisa untuk satu tabel, daftar tabel, atau untuk semua tabel.
Jawaban:
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;
/
AND NOT (t.iot_type IS NOT NULL AND c.constraint_type = 'P')ke segmen kode pertama.
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;
/
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: -
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.
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;
/
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).
Sepertinya Anda tidak dapat melakukan ini dengan satu perintah, tetapi inilah hal terdekat yang dapat saya temukan.
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
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.
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.
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)
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';