Yabancı anahtar referans eylemi nasıl değiştirilir? (davranış)


102

Yabancı anahtara sahip bir sütun içeren bir tablo oluşturdum, şu şekilde ayarlandı ON DELETE CASCADE(ebeveyn silindiğinde çocuğu sil)

Bunu değiştirmek için SQL komutu ne olurdu ON DELETE RESTRICT? (çocukları varsa ebeveyn silinemez)

Yanıtlar:


170

Eski soru ama yardım alabilmek için cevap ekleniyor

İki aşamalı süreci:

Diyelim ki, a'nın sütun adında , kısıtlama adında table1bir yabancı anahtara sahip olduğunu ve anahtarlı tablo olarak adlandırıldığını varsayalım ( şemamda aşağıdaki gibi ). fk_table2_idfk_nametable2t2

   table1 [ fk_table2_id ] --> table2 [t2]

İlk adım , eski KISITLIĞI BIRAKIN: ( referans )

ALTER TABLE `table1` 
DROP FOREIGN KEY `fk_name`;  

uyarı kısıtlaması silindi, sütun silinmedi

İkinci adım , yeni KISITLAMA EKLE:

ALTER TABLE `table1`  
ADD CONSTRAINT `fk_name` 
    FOREIGN KEY (`fk_table2_id`) REFERENCES `table2` (`t2`) ON DELETE CASCADE;  

kısıtlama ekliyor, sütun zaten var

Misal:

UserDetailsTabloda bir tablo var Users:

mysql> SHOW CREATE TABLE UserDetails;
:
:
 `User_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`Detail_id`),
  KEY `FK_User_id` (`User_id`),
  CONSTRAINT `FK_User_id` FOREIGN KEY (`User_id`) REFERENCES `Users` (`User_id`)
:
:

İlk adım:

mysql> ALTER TABLE `UserDetails` DROP FOREIGN KEY `FK_User_id`;
Query OK, 1 row affected (0.07 sec)  

İkinci adım:

mysql> ALTER TABLE `UserDetails` ADD CONSTRAINT `FK_User_id` 
    -> FOREIGN KEY (`User_id`) REFERENCES `Users` (`User_id`) ON DELETE CASCADE;
Query OK, 1 row affected (0.02 sec)  

sonuç:

mysql> SHOW CREATE TABLE UserDetails;
:
:
`User_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`Detail_id`),
  KEY `FK_User_id` (`User_id`),
  CONSTRAINT `FK_User_id` FOREIGN KEY (`User_id`) REFERENCES 
                                       `Users` (`User_id`) ON DELETE CASCADE
:

2
Eklediğiniz kısıtlamanın, orijinal soruda talep edildiği gibi SİLME SINIRI AÇIK olması gerekmez mi?
Numen

Ehm, "silinebilir basamaklama" nedir ve bu neden gereklidir?
Lealo

3
@Noumenon RESTRICT varsayılandır, böylece belirtmediğinizde bunu elde edersiniz.
edruid

1
@Lealo, üst tablodan bir satırı silerseniz (bu durumda Kullanıcılar) alt tablodaki tüm referans satırlarının (UserDetails) da silineceği anlamına gelir.
edruid

1
"ihbar kısıtı, sütun silinmez silinir" notları için teşekkürler, orada değiştirir pratik korunduğunu araçlar veri ve sadece şema tahmin "kısıtlama ekleme, kolon zaten var"
George Birbilis

21

Adını değiştirmek istiyorsanız , bunu tek bir sorguda yapabilirsiniz :

ALTER TABLE table_name
  DROP FOREIGN KEY `fk_name`,
  ADD CONSTRAINT `fk_name2` FOREIGN KEY (`remote_id`)
    REFERENCES `other_table` (`id`)
    ON DELETE CASCADE;

Bu, büyük bir masanız varsa kesinti süresini en aza indirmek için kullanışlıdır.


12
ALTER TABLE DROP FOREIGN KEY fk_name;
ALTER TABLE ADD FOREIGN KEY fk_name(fk_cols)
            REFERENCES tbl_name(pk_names) ON DELETE RESTRICT;

2
çözümü bulmama yardım etti ALTER TABLE table_name ADD...ON DELETE RESTRICT
Moak

3
Hayır, fk_name kısıtlama adıdır. Bir tane sağlamak isteğe bağlıdır. Emin değilim ama belki kullanarak geri alabilirsiniz SHOW CREATE TABLE.
pascal

1
KADEMELİ KISITLAMA muhtemelen amaçlanmamıştır.
jgreep

5

MySQL'in yabancı anahtarı sildikten sonra bir sütunda basit bir indeks tuttuğunu unutmayın. Dolayısıyla, 'referanslar' sütununu değiştirmeniz gerekiyorsa, bunu 3 adımda yapmalısınız.

  • orijinal FK'yi bırak
  • bir dizin bırakın (önceki fk gibi adlar, drop indexcümle kullanarak )
  • yeni FK oluştur

3

Hepsini yönetmek için tek bir sorgu kullanabilirsiniz: ALTER TABLE products DROP FOREIGN KEY oldConstraintName, ADD FOREIGN KEY (product_id, category_id) REFERENCES externalTableName (foreign_key_name, another_one_makes_composite_key) ON DELETE CASCADE ON UPDATE CASCADE


1
bu sadece kısıtlama adını değiştirirseniz işe yarar (eğer otomatik olarak oluşturulmuş bir isim kullanıyorsanız muhtemelen işe
yarar

Sorgu kesinlikle MySQL / MariaDB üzerinde çalışır. Buradaki anahtar, 2. satırda yapılan eski kısıtlamayı ismine göre kaldırmaktır.
stamster

1
hepsi bir arada sorgu sözdizimi, açık kısıtlama adları kullanıldığında MySQL ile benim için çalışmadı
George Birbilis

3

Değiştirmem gereken bir sürü FK vardı, bu yüzden açıklamaları benim için yapacak bir şeyler yazdım. Paylaşacağımı düşündüm:

SELECT

CONCAT('ALTER TABLE `' ,rc.TABLE_NAME,
    '` DROP FOREIGN KEY `' ,rc.CONSTRAINT_NAME,'`;')
, CONCAT('ALTER TABLE `' ,rc.TABLE_NAME,
    '` ADD CONSTRAINT `' ,rc.CONSTRAINT_NAME ,'` FOREIGN KEY (`',kcu.COLUMN_NAME,
    '`) REFERENCES `',kcu.REFERENCED_TABLE_NAME,'` (`',kcu.REFERENCED_COLUMN_NAME,'`) ON DELETE CASCADE;')

FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
LEFT OUTER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
    ON kcu.TABLE_SCHEMA = rc.CONSTRAINT_SCHEMA
    AND kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
WHERE DELETE_RULE = 'NO ACTION'
AND rc.CONSTRAINT_SCHEMA = 'foo'

1
bu, birden çok sütunda bir kısıtlama varsa çalışmaz. oluşturulan sql her sütun için ayrı kısıtlamalar oluşturacak
yanar

Tüm FK'lerim tek sütunlardaydı, bu yüzden bu olasılık hakkında pek düşünmüyordum ama iyi düşündüm
DavidSM
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.