Oracle'daki tüm tablo kısıtlamalarını devre dışı bırakın


96

Oracle'daki tüm tablo kısıtlamalarını tek bir komutla nasıl devre dışı bırakabilirim? Bu, tek bir tablo, bir tablo listesi veya tüm tablolar için olabilir.

Yanıtlar:


148

Geçici biriktirme dosyalarını yazmaktan kaçınmak daha iyidir. Bir PL / SQL bloğu kullanın. Bunu SQL * Plus'tan çalıştırabilir veya bunu bir pakete veya prosedüre koyabilirsiniz. USER_TABLES'e katılım, görüntüleme kısıtlamalarını önlemek için var.

Tüm kısıtlamaları (NOT NULL, birincil anahtarlar vb. Dahil) gerçekten devre dışı bırakmak istemeniz olası değildir. WHERE yan tümcesine constraint_type koymayı düşünmelisiniz.

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

Kısıtlamaları tekrar etkinleştirmek biraz aldatıcıdır - bir yabancı anahtar kısıtlamasında bunlara başvurmadan önce birincil anahtar kısıtlamalarını etkinleştirmeniz gerekir. Bu, kısıt_türü üzerinde ORDER BY kullanılarak yapılabilir. 'P' = birincil anahtar, 'R' = yabancı anahtar.

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
Bu ilk kod segmenti, yabancı anahtarları devre dışı bırakmadan önce birincil anahtarları devre dışı bırakmaya çalışmayacak mı?
David Aldridge

@David Sanırım ilk segmentte bu konuyla karşılaştım. 'ORDER BY c.constraint_type' ile kapanış ') arasına' DESC 'ekleyerek çözdüm
AndreiM

@WW Minnettarlığım. Bu, beni Enable ve Disable kısıtlama ifadelerini oluşturmak için bir SQL ifadesi yazma zahmetinden kurtardı.
dave

1
Dizinle düzenlenmiş tablolarda birincil anahtarlar devre dışı bırakılamaz. Bunları AND NOT (t.iot_type IS NOT NULL AND c.constraint_type = 'P'), ilk kod segmentine ekleyerek halledebilirsiniz .
Andrew Miller

2
Uyarı: Zaten DEVRE DIŞI kısıtlamalarınız varsa, tüm kısıtlamalar bu PL / SQL prosedürü kullanılarak etkinleştirilecektir. Devre dışı bırakıldıklarından emin olmak için bu kısıtlamaları filtrelemelisiniz.
nachouve

11

Kısıtlamalar arasındaki bağımlılıkları saymak için:

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

Bu tek bir komut değil, ama işte bunu nasıl yapıyorum. Aşağıdaki komut dosyası SQL * Plus'ta çalışacak şekilde tasarlanmıştır. Not, bunu bilerek yalnızca mevcut şema içinde çalışmak için yazdım.

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

Neyi düşürdüğünüzü kısıtlamak için filtre, select deyimine bir where cümlesi ekleyin: -

  • kısıtlama türü için filtre uygulayarak yalnızca belirli kısıtlama türlerini kaldırır
  • bunu yalnızca bir veya birkaç tablo için yapmak üzere tablo_adı üzerinde filtreleyin.

Mevcut şemadan daha fazlası üzerinde çalıştırmak için, select deyimini user_constraints yerine all_constraints arasından seçim yapacak şekilde değiştirin.

Not - bazı nedenlerden dolayı, alt çizginin önceki paragrafta italik hale getirilmiş gibi davranmamasını sağlayamıyorum. Birisi bunu nasıl düzelteceğini biliyorsa, lütfen bu yanıtı düzenlemekten çekinmeyin.


Kısıtlamaları DROP yapmak yerine DEVRE DIŞI BIRAKMAK istiyorsanız, yukarıdaki SELECT ifadesini düzenleyin: 'kısıtlamayı devre dışı bırak' HTH: o)
Andrew

Evet, bu iyi bir öneri - gelecekte bu bilgileri eklemek için yayını düzenlemekten çekinmeyin. Bu yüzden yayınlarımı topluluk wiki'si düzenlenebilir olarak görüyorum.
Mike McAllister

5

Tüm kısıtlamaları devre dışı bırakmak için aşağıdaki imleci kullanın .. Ve kısıtlamaları etkinleştirmek için sorguyu değiştirin ...

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

Bu, basitçe DBA / ALL / USER_CONSTRAINTS sistem görünümüne dayalı olarak PL / SQL'de yazılabilir, ancak çeşitli ayrıntılar göründüğü kadar önemsiz değildir. Bunun yapılma sırasına dikkat etmelisiniz ve ayrıca benzersiz dizinlerin varlığını da hesaba katmalısınız.

Sıra önemlidir, çünkü bir yabancı anahtar tarafından referans verilen benzersiz veya birincil bir anahtarı bırakamazsınız ve diğer şemalardaki tablolarda kendi başınıza birincil anahtarlara başvuran yabancı anahtarlar olabilir, bu nedenle HERHANGİ BİR TABLO DEĞİŞTİR ayrıcalığına sahip değilseniz bu PK'leri ve UK'leri bırakamaz. Ayrıca, benzersiz bir dizini benzersiz olmayan bir dizin olarak değiştiremezsiniz, bu nedenle kısıtlamayı kaldırmak için onu kaldırmanız gerekir (bu nedenle benzersiz kısıtlamaları bir "gerçek" kısıtlama olmayan ve -birik indeks).


0

Bunu tek bir komutla yapabilecekmişsiniz gibi görünmüyor, ama işte bulabildiğim ona en yakın şey.


0

Bu, kısıtlamaları devre dışı bırakmanın başka bir yoludur ( https://asktom.oracle.com/pls/asktom/f?p=100:11:2402577774283132::::P11_QUESTION_ID:399218963817 adresinden geldi )

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;

tıkır tıkır çalışıyor


0

"Devre dışı bırak" komut dosyasında, maddeye göre sıralama şu şekilde olmalıdır:

ORDER BY c.constraint_type DESC, c.last_change DESC

Bu maddenin amacı, kısıtlamaları doğru sırada devre dışı bırakmaktır.


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; 

Bu ifade, birincil anahtar, yabancı anahtarlar ve diğer kısıtlamalar dahil tüm kısıtlamaları kapatan komutları döndürür.


0

döngü için imleç ile (kullanıcı = 'TRANEE', tablo = '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;
/

(Devre dışı bırakmayı etkinleştirmek için değiştirirseniz, tüm kısıtlamaları etkinleştirebilirsiniz)


0

Aşağıdaki sorgu tarafından döndürülen tüm komutları çalıştırabilirsiniz:

'ALTER TABLE' seçin || substr (c.table_name, 1,35) || 'KISITLAMAYI DEVRE DIŞI BIRAK' || kısıt_adı || ' ; ' user_constraints'ten c --burada c.table_name = 'TABLE_NAME';

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.