ALTER TABLE deyiminde 'ON DELETE CASCADE' nasıl eklenir


130

Tablomda yabancı anahtar kısıtlaması var, buna ON DELETE CASCADE eklemek istiyorum.

Bunu denedim:

child_table_name tablosunu değiştir
  fk_name kısıtlamasını değiştir
  yabancı anahtar (child_column_name)
  basamaklı silme sırasında parent_table_name (parent_column_name);

Çalışmıyor.

DÜZENLEME:
Yabancı anahtar zaten var, yabancı anahtar sütununda veri var.

İfadeyi yürüttükten sonra aldığım hata mesajı:

ORA-02275: böyle bir başvuru kısıtlaması tabloda zaten mevcut

Sorun ne? İfade reddedilir, silme işlemi gerçekleşmez ..
Thorsten

Yanıtlar:


162

ON DELETE CASCADEZaten var olan bir kısıtlamaya ekleme yapamazsınız . Kısıtlamanız gerekecek dropve yeniden createsınırlandıracaksınız. Dokümantasyon olduğunu gösterir MODIFY CONSTRAINTMadde sadece değiştirebilir bir kısıtlama durumunu (yani: ENABLED/DISABLED...).


86

Önce dropyabancı anahtarınızı add constraintyerine koyun ve yukarıdaki komutu deneyin modify constraint. Şimdi komut şu:

ALTER TABLE child_table_name 
  ADD CONSTRAINT fk_name 
  FOREIGN KEY (child_column_name) 
  REFERENCES parent_table_name(parent_column_name) 
  ON DELETE CASCADE;

24
Bize kodun tamamını veriyor, bu, postgres ile hiçbir ilgisi olmayan insanlar için açık bir avantajdır
Matthis Kohli

1
@WiiMaxx Kurucu kıskanç bir adam. lol Bu cevap, kodu da sağladığından, ilk cevaptan daha önemli ..
Ben En Aptal

11

Bu PL * SQL, DBMS_OUTPUT'a silme kademesine sahip olmayan her kısıtlamayı bırakacak ve silme kademeli olarak yeniden oluşturacak bir komut dosyası yazacaktır.

NOT: Bu komut dosyasının çıktısını çalıştırmak KENDİ RİSKİNİZDİR. Elde edilen komut dosyasını okumak ve yürütmeden önce düzenlemek en iyisidir.

DECLARE
      CURSOR consCols (theCons VARCHAR2, theOwner VARCHAR2) IS
        select * from user_cons_columns
            where constraint_name = theCons and owner = theOwner
            order by position;
      firstCol BOOLEAN := TRUE;
    begin
        -- For each constraint
        FOR cons IN (select * from user_constraints
            where delete_rule = 'NO ACTION'
            and constraint_name not like '%MODIFIED_BY_FK'  -- these constraints we do not want delete cascade
            and constraint_name not like '%CREATED_BY_FK'
            order by table_name)
        LOOP
            -- Drop the constraint
            DBMS_OUTPUT.PUT_LINE('ALTER TABLE ' || cons.OWNER || '.' || cons.TABLE_NAME || ' DROP CONSTRAINT ' || cons.CONSTRAINT_NAME || ';');
            -- Re-create the constraint
            DBMS_OUTPUT.PUT('ALTER TABLE ' || cons.OWNER || '.' || cons.TABLE_NAME || ' ADD CONSTRAINT ' || cons.CONSTRAINT_NAME 
                                        || ' FOREIGN KEY (');
            firstCol := TRUE;
            -- For each referencing column
            FOR consCol IN consCols(cons.CONSTRAINT_NAME, cons.OWNER)
            LOOP
                IF(firstCol) THEN
                    firstCol := FALSE;
                ELSE
                    DBMS_OUTPUT.PUT(',');
                END IF;
                DBMS_OUTPUT.PUT(consCol.COLUMN_NAME);
            END LOOP;                                    

            DBMS_OUTPUT.PUT(') REFERENCES ');

            firstCol := TRUE;
            -- For each referenced column
            FOR consCol IN consCols(cons.R_CONSTRAINT_NAME, cons.R_OWNER)
            LOOP
                IF(firstCol) THEN
                    DBMS_OUTPUT.PUT(consCol.OWNER);
                    DBMS_OUTPUT.PUT('.');
                    DBMS_OUTPUT.PUT(consCol.TABLE_NAME);        -- This seems a bit of a kluge.
                    DBMS_OUTPUT.PUT(' (');
                    firstCol := FALSE;
                ELSE
                    DBMS_OUTPUT.PUT(',');
                END IF;
                DBMS_OUTPUT.PUT(consCol.COLUMN_NAME);
            END LOOP;                                    

            DBMS_OUTPUT.PUT_LINE(')  ON DELETE CASCADE  ENABLE VALIDATE;');
        END LOOP;
    end;

11

Daha önce açıklandığı gibi:

ALTER TABLE TABLEName
drop CONSTRAINT FK_CONSTRAINTNAME;

ALTER TABLE TABLENAME
ADD CONSTRAINT FK_CONSTRAINTNAME
    FOREIGN KEY (FId)
    REFERENCES OTHERTABLE
        (Id)
    ON DELETE CASCADE ON UPDATE NO ACTION;

Gördüğünüz gibi, komutların ayrılması gerekiyor, önce bırakıp sonra ekliyoruz.


Bu Oracle için geçersiz
a_horse_with_no_name

Sadece SqlServer'da test edildi, ancak gopostgres ve SqlServer'ın kendisinde olduğu gibi noktalı virgülle şansa sahip olmanız mümkün . Ancak kalan temel kodlar sql standardıdır. Noktalı virgüllerle test et, az önce değiştirdim
David Silva-Barrera

[Veya ]standart SQL (ve Oracle) 'de geçersiz edilmektedir. Oracle ayrıca on updateyabancı anahtar için yan tümceyi desteklemez .
a_horse_with_no_name

Haklısın, [ ]SqlServer'a özel. Daha çok temizleyeceğim. Hakkında on updatehiçbir şey söyleyemem.
David Silva-Barrera

11

MYSQL KULLANICILARI için cevap:

ALTER TABLE ChildTableName 
DROP FOREIGN KEY `fk_table`;
ALTER TABLE ChildTableName 
ADD CONSTRAINT `fk_t1_t2_tt`
  FOREIGN KEY (`parentTable`)
  REFERENCES parentTable (`columnName`)
  ON DELETE CASCADE
  ON UPDATE CASCADE;

StackOverflow'a hoş geldiniz. Lütfen stackoverflow.com/editing-help adresindeki kodu biçimlendirme hakkında bilgi edinin . Daha okunaklı hale getirmek için kodu sizin için düzenledim.
Adrian W

3

MySQL kullanan herkes için:

Eğer kafa varsa PHPMYADMINyapmanız gereken tek şey tıklamak, güncelleştirmenin istediğiniz yabancı anahtar vardır tabloya web sayfası ve gezinme Relational view bulunan Structuresekmesine ve değiştirmek On deleteiçin seçme menü seçeneğini Cascade.

Aşağıda gösterilen resim:

görüntü açıklamasını buraya girin


OP, 2009 yılından itibaren Oracle sorusu etiketlenmiştir ve PHPMYADMIN, MySQL için üçüncü taraf bir yazılım bileşenidir.
vegatripy

7
Kesinlikle doğru. Ama bu soruyu Google'da araştırdım, bunu MySQL'de nasıl yapacağımı öğrenmek istedim ve Google beni buraya getirdi. Evet, soru Oracle ile etiketlendi, bu yüzden bu cevap doğru değil ... ama bu Cevaba rastlayan benim gibi okuyucular için faydalı olacak. Yani yok o Oracle özgü olmasa bile, bu sayfaya değer katmak. Yani, teşekkürler James111!
Mike Gledhill

3

İşte kullanışlı bir çözüm! SQL Server 2008 R2 kullanıyorum.

ON DELETE / UPDATE CASCADE ekleyerek FK kısıtlamasını değiştirmek istediğinizde şu adımları izleyin:

1 NUMARA:

Kısıtlamaya sağ tıklayın ve Değiştir için tıklayın

görüntü açıklamasını buraya girin

2 NUMARA:

Sol tarafta kısıtlamanızı seçin (birden fazla varsa). Sonra sağ tarafta, " INSERT And UPDATE Specification " noktasını daraltın ve ihtiyacınıza göre Kuralı Sil veya Güncelle satırındaki eylemleri belirtin. Bundan sonra iletişim kutusunu kapatın.

görüntü açıklamasını buraya girin

3 NUMARA:

Son adım, bu değişiklikleri kaydetmek (tabii ki!)

görüntü açıklamasını buraya girin

Not: Başka bir tabloda referans verilen bir birincil anahtarı değiştirmek istediğim için beni bir sürü işten kurtardı.


Mükemmel, tam da ihtiyacım olan şey!
Wildview

1

Bir yabancı anahtarı düşürmeden değiştirmek isterseniz şunları yapabilirsiniz:

ALTER TABLE child_table_name  WITH CHECK ADD FOREIGN KEY(child_column_name)
REFERENCES parent_table_name (parent_column_name) ON DELETE CASCADE

0
ALTER TABLE `tbl_celebrity_rows` ADD CONSTRAINT `tbl_celebrity_rows_ibfk_1` FOREIGN KEY (`celebrity_id`) 
REFERENCES `tbl_celebrities`(`id`) ON DELETE CASCADE ON UPDATE RESTRICT;
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.