MySQL "Cannot add or update a child row" — Foreign Key Neden Reddediyor?
1452 ve 1451 hatalarının farkı, karakter seti/veri tipi uyuşmazlığı, yetim satırları bulma sorgusu ve toplu yüklemede doğru yöntem.
Hata mesajı semptomdur, kök neden değildir. Sunucuyu yeniden başlatmadan veya rastgele ayar değiştirmeden önce aşağıdaki "Nedeni ayırt eden tek sorgu"yu çalıştırarak gerçek senaryoyu netleştirin.
▸Belirti
ERROR 1452 (23000): Cannot add or update a child row: a foreign key
constraint fails (`app`.`siparis`, CONSTRAINT `fk_siparis_musteri`
FOREIGN KEY (`musteri_id`) REFERENCES `musteri` (`id`))Mesajın kendisi tabloyu, kısıt adını ve kolonu verir — bu yüzden teşhis basittir. Karıştırılan nokta şudur: 1452 ve 1451 iki ayrı hatadır.
- •1452 →
INSERT/UPDATE: Çocuk tabloya, ebeveynde karşılığı olmayan bir değer yazılmak isteniyor. - •1451 →
DELETE/UPDATE: Ebeveyn silinmek isteniyor ama bağlı çocuk kayıtlar var.
▸Adım adım çözüm
1. Suçlu satırları bulun. Tek tek denemek yerine, ebeveyni olmayan çocuk kayıtları toplu listeleyin:
SELECT c.*
FROM siparis c
LEFT JOIN musteri p ON p.id = c.musteri_id
WHERE c.musteri_id IS NOT NULL
AND p.id IS NULL
LIMIT 50;Bu sorgu "ebeveyni olmayan yetim çocuk kayıtlarını" verir. Boş dönüyorsa sorun veri değil, şema uyuşmazlığıdır — 2. adıma geçin.
2. Veri tipi ve karakter setini karşılaştırın. Foreign key, iki kolonun tipinin birebir aynı olmasını gerektirir. INT ile BIGINT, INT UNSIGNED ile INT, utf8mb4 ile latin1 eşleşmez:
SELECT table_name, column_name, column_type,
character_set_name, collation_name
FROM information_schema.columns
WHERE table_schema = DATABASE()
AND column_name = 'musteri_id';MySQL 8.0'da bu tür bir uyuşmazlık ERROR 3780 (HY000): Referencing column ... and referenced column ... are incompatible verir. Çözüm: ALTER TABLE ... MODIFY COLUMN ile tipleri eşitlemektir.
3. Toplu yüklemede sırayı düzeltin. mysqldump çıktısını yüklerken yabancı anahtar kontrolleri yüzünden sıra bozulabilir. Doğru yöntem:
SET FOREIGN_KEY_CHECKS = 0;
-- yükleme komutları
SET FOREIGN_KEY_CHECKS = 1;4. Silme hatası (1451) alıyorsanız: İki seçenek var: çocukları önce silmek, ya da şemada kaskad kuralı tanımlamak:
ALTER TABLE siparis
ADD CONSTRAINT fk_siparis_musteri
FOREIGN KEY (musteri_id) REFERENCES musteri(id)
ON DELETE CASCADE;ON DELETE CASCADE'i bilinçli seçin: bir müşteri silindiğinde tüm sipariş geçmişi kalıcı silinir. Finansal kayıtlarda ON DELETE RESTRICT (varsayılan) daha güvenlidir.
▸Bunu bir daha yaşamamak için
Yabancı anahtar ihlallerini bir uygulama hatası değil, veri bütünlüğü alarmı olarak ele alın: bu hata düzenli olarak görülüyorsa ya bir servis ebeveyn kaydı oluşturmadan çocuk yazıyor, ya da bir yerde FOREIGN_KEY_CHECKS = 0 kalıcı hale gelmiştir.
- •İlgili Hata: MySQL 1213 Deadlock Çözümü
- •İlgili Hata: MySQL 1205 Lock Wait Timeout Exceeded
Diğer Veritabanı Hata Teşhisleri
Kriz anında başvurabileceğiniz diğer doğrulanmış hata rehberleri.
PostgreSQL too many clients already Hatası: 6 Adımda Çözüm
FATAL: sorry, too many clients already hatasının üç nedeni, nedeni ayırt eden tek sorgu ve max_connections ile PgBouncer üzerinden kalıcı çözümü.
PostgreSQL password authentication failed Hatası: Neden ve Çözüm
psql password authentication failed hatasının dört nedeni: yanlış şifre, md5/SCRAM uyuşmazlığı, pg_hba.conf sırası ve yanlış cluster. Adım adım teşhis.
MySQL ERROR 1045 Access denied: root Şifresi Sıfırlama Rehberi
MySQL 1045 hatasının dört nedeni, "using password: YES/NO" ayrımının anlamı ve kilitli kalınca --init-file ile güvenli şifre sıfırlama.