MySQL hatası 1452 - Bir alt satır eklenemiyor veya güncellenemiyor: yabancı anahtar kısıtlaması başarısız oluyor


237

Biraz garip bir sorun yaşıyorum. Başka bir başvuru bir tabloya yabancı anahtar eklemek çalışıyorum, ama bir nedenle başarısız oluyor. Sınırlı MySQL bilgimle, muhtemelen şüphelenilebilecek tek şey, farklı bir tabloda başvurmaya çalıştığım referansı gösteren yabancı bir anahtar olması.

Ben her SHOW CREATE TABLEiki tabloda bir sorgu yaptım sourcecodes_tags, yabancı anahtar ile tablo sourcecodes, başvurulan tablodur.

CREATE TABLE `sourcecodes` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 `user_id` int(11) unsigned NOT NULL,
 `language_id` int(11) unsigned NOT NULL,
 `category_id` int(11) unsigned NOT NULL,
 `title` varchar(40) CHARACTER SET utf8 NOT NULL,
 `description` text CHARACTER SET utf8 NOT NULL,
 `views` int(11) unsigned NOT NULL,
 `downloads` int(11) unsigned NOT NULL,
 `time_posted` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 PRIMARY KEY (`id`),
 KEY `user_id` (`user_id`),
 KEY `language_id` (`language_id`),
 KEY `category_id` (`category_id`),
 CONSTRAINT `sourcecodes_ibfk_3` FOREIGN KEY (`language_id`) REFERENCES `languages` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
 CONSTRAINT `sourcecodes_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
 CONSTRAINT `sourcecodes_ibfk_2` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1

CREATE TABLE `sourcecodes_tags` (
 `sourcecode_id` int(11) unsigned NOT NULL,
 `tag_id` int(11) unsigned NOT NULL,
 KEY `sourcecode_id` (`sourcecode_id`),
 KEY `tag_id` (`tag_id`),
 CONSTRAINT `sourcecodes_tags_ibfk_1` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1

Hatayı oluşturan kod budur:

ALTER TABLE sourcecodes_tags ADD FOREIGN KEY (sourcecode_id) REFERENCES sourcecodes (id) ON DELETE CASCADE ON UPDATE CASCADE

2
hataya neden olan ekleme / güncelleme komutunuzu da gönderebilir misiniz?
Zed

64
bu yabancı anahtarı eklediğinizde tablolarınız boş mu?
Zed

12
gerçek bir kimlik olmayan herhangi bir sourcecode_id olup olmadığını görmek için bu sorguyu çalıştırmayı deneyin: SELECT sourcecode_id FROM sourcecodes_tags NEREDE sourcecode_id NOT IN (SELECT id FROM kaynak kodları AS tmp);
Zed

11
Teşekkürler Zed, bu tablolardan birinde veri vardı sorun oldu. Şimdi düşünmek başarısız olduğu için mantıklı çünkü mevcut olmayan öğelere atıfta bulunan şeyler vardı, ama bunu asla tahmin edemezdim. Teşekkürler!
Zim

2
Tablo boşsa neden başarısız oluyor?
theblackpearl

Yanıtlar:


226

Büyük olasılıkla sourcecodes_tagstablonuzda sourcecode_idartık sourcecodestablonuzda bulunmayan değerler var . Önce onlardan kurtulmalısın.

İşte bu kimlikleri bulabilen bir sorgu:

SELECT DISTINCT sourcecode_id FROM 
   sourcecodes_tags tags LEFT JOIN sourcecodes sc ON tags.sourcecode_id=sc.id 
WHERE sc.id IS NULL;

UPDATE sourcecodes_tags SET sourcecode_id = NULL WHERE sourcecode_id NOT IN (SELECT id FROM sourcecodes)bu kimliklerden kurtulmaya yardımcı olmalı. Veya nullizin verilmiyorsa sourcecode_id, bu satırları kaldırın veya eksik değerleri sourcecodestabloya ekleyin .
naXa

Ben de aynı şeyi düşünüyordum, ama benim için SELECT Tchild.id FROM Tchild INNER JOIN Tmain ON Tmain.id = Tchild.fk_id WHERE Tmain.id IS NULLhiçbir şey döndürmüyor, bu yüzden sorun başka bir yerde!
Meloman

Ahh benim için sorun buydu. UPDATE `homestead`.`automations` SET `deleted_at`=NULL WHERE deleted_at IS NOT NULL;Yabancı bir anahtar içermeyen kaçmaya çalışıyordum , bu yüzden kafam karıştı. Ancak kişi tablomda otomasyon tablosunun atıfta bulunduğu bazı kayıtlar eksik olması, "Hata Kodu: 1452. Bir alt satır eklenemiyor veya güncellenemiyor: bir yabancı anahtar kısıtlaması başarısız".
Ryan

99

MySQL veritabanımla aynı sorunu yaşadım ama sonunda benim için çalışan bir çözüm buldum.
Masamda her şey mysql bakış açısından iyi olduğundan (her iki tablo da InnoDB motorunu kullanmalı ve her sütunun veri türü yabancı anahtar kısıtlamasında yer alan aynı türden olmalıdır).
Yaptığım tek şey yabancı anahtar kontrolünü devre dışı bırakmak ve daha sonra yabancı anahtar işlemini gerçekleştirdikten sonra etkinleştirmekti.
Attığım adımlar:

SET foreign_key_checks = 0;
alter table tblUsedDestination add constraint f_operatorId foreign key(iOperatorId) references tblOperators (iOperatorId); Query
OK, 8 rows affected (0.23 sec) Records: 8  Duplicates: 0  Warnings: 0
SET foreign_key_checks = 1;

49
foreign_key_checks bir nedenle var. Kısıtlamayı ihlal ettiği için yabancı anahtarı ekleyemiyorsanız, önce verileri düzeltmelisiniz. Çeklerin kapatılması ve ardından anahtarın eklenmesi sizi tutarsız bir durumda bırakır. Yabancı anahtar kontrolleri ek yük ekler, eğer bunları kullanmak istemiyorsanız, bunun yerine myisam kullanın.
cs_alumnus

5
@AbuSadatMohammedYasin hayır olmamalı: soru "neler olduğunu" sordu ve bu cevap basitçe açıklamaya çalışmaz. Cs_alumnus'un belirttiği gibi, daha büyük bir sorun vardır: diğer tabloda ( Yabancı anahtarın yapması gerektiği gibi) başka bir değere başvurması gereken tüm yeni değerler, tutarsız bir durum yaratarak hiçbir şeye işaret etmeyebilir. Cayetano'nun kısa ve etkili açıklaması , kısıtlama oluşturmadan önce hangi değerleri güncellemeniz gerektiğini bulmanızı sağlar, böylece var olması gereken değerleri döndürmesi gereken sorgular sizi şaşırtmaz!
Armfoot

55

Kullanım NOT INkısıtlamaları nerede bulmak için kısıtlayıcı :

SELECT column FROM table WHERE column NOT IN 
(SELECT intended_foreign_key FROM another_table)

yani daha spesifik olarak:

SELECT sourcecode_id FROM sourcecodes_tags WHERE sourcecode_id NOT IN 
(SELECT id FROM sourcecodes)

EDIT: INve NOT INoperatörlerin operatörlerden çok daha hızlı olduğu, JOINayrıca inşa edilmesi ve tekrarlanması çok daha kolay olduğu bilinmektedir .


1
Bunu doğru anlarsam, zaten içinde veri bulunan bir tabloya yabancı anahtar ekleyebiliriz, ancak yalnızca üst tablodaki her satır için bir alt satır varsa? Üst tablodaki her satır için alt satır yoksa (sorgunuzun bulduğu şey budur), yabancı anahtar komut dosyası başarısız olur.
Vincent

@Vincent, üst tablo tarafından referans alınan tabloyu kastediyorsanız, evet! Bu nedenle Cayetano'nun seçilmesiyle, yeni kısıtlamayı (FK) eklemeden önce "alt" tablonuzdan güncellemeniz / kaldırmanız gereken tüm satırları alırsınız. Hepsi "another_table" daki değerlere işaret ettikten sonra gitmekte fayda var!
Armfoot

23

Tabloları kesin ve ardından FK Constraint'i eklemeyi deneyin .

Bu çözümün biraz garip olduğunu biliyorum ama% 100 çalışıyor. Ama bunun problemle başa çıkmak için ideal bir çözüm olmadığını kabul ediyorum, ama umarım yardımcı olur.


4
Her şeyi kesmeye gerek yok. "UPDATE sourcecodes_tags SET sourcecode_id = NULL NEREDE sourcecode_id NOT IN (Kaynak kodlarından SELECT id)" yeterli olmalıdır. Veya "sourcecode_id" öğesinde null değerine izin verilmiyorsa, bu satırları kaldırın veya eksik değerleri "kaynak kodları" tablosuna ekleyin.
Torben

1
Bazen, veri otomatik arttırma PK'sini arttırırsa, sizi kesilmeye zorlar.
François Breton

2
@ShankarDamodaran tabloyu neden kesiyor emin değilim ama bu çözüm benim için iyi çalıştı. İlişkilerimin işe yaramasını sağladım ... TEŞEKKÜRLER!
MizAkita

@MizAkita, diğer tabloda karşılık gelen değeri olmayan satırları silerek yeni kısıtlamanın oluşturulmasına izin verdiği için çalışır. Bu satırları bulup güncelleyip silerseniz ( Cayetano'nun önerisi gibi ), diğer satırları silmenize gerek yoktur ...
Armfoot

@Armfoot - Yabancı anahtar ile tabloya ilk satırı eklerken bu sorunu yaşadım. Arayacak hiçbir satırım yoktu.
Krewetka

16

Benim için bu problem biraz farklı ve kontrol edilmesi ve çözülmesi çok kolaydı.

Tablolarınızın HER İKİSİNİN InnoDB olduğundan emin olmalısınız. Tablolardan biri, yani referans tablosu bir MyISAM ise, kısıtlama başarısız olur.

    SHOW TABLE STATUS WHERE Name =  't1';

    ALTER TABLE t1 ENGINE=InnoDB;

14

Child.column değerinin zaten 0 değeri varsa ve parent.id değerinin 0 olmaması durumunda, parent.id için child.column öğesine bir yabancı anahtar ayarlandığında da bu olur.

Her child.column öğesinin NULL olduğundan veya parent.id dosyasında varolan bir değere sahip olduğundan emin olmanız gerekir.

Ve şimdi nos'un yazdığı ifadesini okuduğumda, doğruladığı şey bu.


14

Bugün de aynı sorunu yaşadım. Dört şeyi test ettim, bazıları burada zaten bahsetti:

  1. Alt sütununuzda üst sütunda bulunmayan herhangi bir değer var mı (alt sütun geçersiz kılınmışsa NULL dışında)

  2. Alt ve üst sütunlar aynı veri türüne sahip mi?

  3. Başvurduğunuz üst sütunda bir dizin var mı? MySQL, performans açısından bunu gerektiriyor gibi görünüyor ( http://dev.mysql.com/doc/refman/5.5/en/create-table-foreign-keys.html )

  4. Ve bu benim için çözdü: Her iki tablonun da aynı harmanlaması var mı?

UTF-8'de bir tablo ve iso-bir şeyde diğeri vardı. Bu işe yaramadı. İzo-tablosu UTF-8 harmanlaması olarak değiştirildikten sonra kısıtlamalar sorunsuz bir şekilde eklenebilir. Benim durumumda, phpMyAdmin, yabancı anahtar kısıtlaması oluşturmak için açılır menüde iso tablosunda alt tabloyu bile göstermedi.


7

Sütun satırı 0 için geçerli bir yabancı anahtar olmayan geçersiz bir değer var gibi görünüyor, bu nedenle MySQL bunun için bir yabancı anahtar kısıtlaması ayarlayamıyor.

Bu adımları takip edebilirsiniz:

  1. FK kısıtlamasını ayarlamaya çalıştığınız sütunu bırakın.

  2. Tekrar ekleyin ve varsayılan değerini NULL olarak ayarlayın.

  3. Bunun için bir yabancı anahtar kısıtlaması ayarlamaya çalışın.


5

Ben aynı sorun, tablolarımın satırları kontrol ve bir yabancı anahtar tanımlamak istediğim alanların değeri ile bazı uyumsuzluk olduğunu bulundu. Bu değeri düzelttim, tekrar denedim ve sorun çözüldü.


4

Sonunda benim tablodaki tüm verileri silin ve alter yeniden çalıştırın. İşe yarıyor. Parlak değil, ama çok zaman kazandırır, özellikle uygulamanız herhangi bir müşteri verisi olmadan geliştirme aşamasındadır.


4

bunu dene

SET foreign_key_checks = 0;

ALTER TABLE sourcecodes_tags ADD FOREIGN KEY (sourcecode_id) REFERENCES sourcecodes (id) ON DELETE CASCADE ON UPDATE CASCADE

SET foreign_key_checks = 1;

2

Aynı problemi üç farklı kez yaşadım. Her örnekte, kayıtlarımdan biri (veya daha fazlası) yeni yabancı anahtarla uyumlu değildi. Anahtarın kendisini eklemeye çalışmadan önce, yabancı anahtarın sözdizimi kısıtlamalarına uymak için mevcut kayıtlarınızı güncellemek isteyebilirsiniz. Aşağıdaki örnek genellikle sorun kayıtlarını ayırmalıdır:

SELECT * FROM (tablename)
    WHERE (candidate key) <> (proposed foreign key value) 
        AND (candidate key) <> (next proposed foreign key value)

AND (candidate key) <> (next proposed foreign key value)yabancı anahtardaki her değer için sorgunuzda tekrarlayın .

Bir ton kaydınız varsa bu zor olabilir, ancak tablonuz oldukça küçükse çok uzun sürmemelidir. SQL sözdiziminde süper şaşırtıcı değilim, ama bu her zaman benim için sorunu izole etti.


2

Her iki tablonuzun verilerini boşaltın ve komutu çalıştırın. Çalışacak.


VHanded de aynı cevabı 3 yıl önce verdi. Umarım tablolarda önemli bir veri yoktur ...
xlecoustillier


1

Bu çözümleri hazırlıyordum ve bu örnek yardımcı olabilir.

Veritabanımın kimlikleri için birincil anahtarları olan iki tablo (e-posta ve kredi kartı) var. Başka bir tablo (istemci) bu tablo kimliklerini yabancı anahtarlar olarak ifade eder. E-posta istemcisi verileri dışında bir neden var.

Önce referans verilen tablolar (e-posta, credit_card) için satır verilerini ekler, sonra her birinin kimliğini alırsınız, bu kimlikler üçüncü tabloda (istemci) gereklidir.

İlk olarak başvurulan tablolara satır eklemezseniz, üçüncü tabloya yabancı anahtarlara başvuran yeni bir satır eklediğinizde MySQL yazışmaları yapamaz.

İlk olarak başvurulan tablolar için başvurulan satırları, daha sonra yabancı anahtarları gösteren satırı eklerseniz, hata oluşmaz.

Bu yardımcı olur umarım.


mysql> e-posta (e-posta) değerlerine ekle ('xxx@yyy.com'); mysql> ndtc (ndtc, yıl, ay) değerlerine ('1111222233334444', '2000', '01') ekleyin; mysql> cliente (nombres, apellidos, telefono, idNDTC, idEmail) değerleri ('myname', 'myapp', '5555555555', 1,1);
SubstanceMX

1

Değerin diğer tabloda olduğundan emin olun, aksi takdirde atanan ilgili sütunda bu hatayı alırsınız.

Sütun atanmışsa, başka bir tablonun satır kimliğine atanmışsa, tabloda bir satır olduğundan emin olun, aksi takdirde bu hata görünecektir.


1

bu örneği deneyebilirsin

 START TRANSACTION;
 SET foreign_key_checks = 0;
 ALTER TABLE `job_definers` ADD CONSTRAINT `job_cities_foreign` FOREIGN KEY 
 (`job_cities`) REFERENCES `drop_down_lists`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
 SET foreign_key_checks = 1;
 COMMIT;

Not: phpmyadmin kullanıyorsanız Yabancı anahtar kontrollerini etkinleştir seçeneğinin işaretini kaldırın

olarak , örneğin resim açıklamasını buraya girin

umut bu soloution sorunu çözmek :)


1

Sadece bir soruya cevap vermeniz gerekiyor:

Tablonuz zaten veri depolıyor mu? (Özellikle tablo yabancı anahtarı içeriyordu.)

Cevabınız evet ise, yapmanız gereken tek şey tüm kayıtları silmek, o zaman tablonuza herhangi bir yabancı anahtar ekleyebilirsiniz.

Talimatı sil: Alt öğeden (yabancı anahtar tablosu içeren) ana tabloya.

Veri girişlerinden sonra yabancı anahtarı ekleyememenizin nedeni tablo tutarsızlığından kaynaklanıyor, tabloyu doldurmuş olan eski veri üzerinde yeni bir yabancı anahtarla nasıl başa çıkacaksınız?

Yanıt hayırsa, diğer talimatları izleyin.


0
UPDATE sourcecodes_tags
SET sourcecode_id = NULL
WHERE sourcecode_id NOT IN (
  SELECT id FROM sourcecodes);

bu kimliklerden kurtulmaya yardımcı olmalı. Veya nullizin verilmiyorsa sourcecode_id, bu satırları kaldırın veya eksik değerleri sourcecodestabloya ekleyin .


0

Aynı problemi yaşadım ve yabancı anahtar sütununa koymak NULLyerine çözüm buldum NOT NULL. İşte bir sorgu:

ALTER TABLE `db`.`table1`
ADD COLUMN `col_table2_fk` INT UNSIGNED NULL,
ADD INDEX `col_table2_fk_idx` (`col_table2_fk` ASC),
ADD CONSTRAINT `col_table2_fk1`
FOREIGN KEY (`col_table2_fk`)
REFERENCES `db`.`table2` (`table2_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;

MySQL bu sorguyu yürüttü!


0

Benim durumumda, aynı yapıya sahip yeni bir tablo oluşturdum, diğer tablolarla ilişkileri oluşturdum, sonra CSV'deki sorunu eski tablodan çıkardım, sonra CSV'yi yeni tabloya aktardım ve yabancı anahtar denetimini devre dışı bıraktım ve devre dışı bırakma içe aktarma kesintisi, tüm verilerim başarıyla sorun olmayan yeni tabloya eklenir, ardından eski tabloyu siler.

Benim için çalıştı.

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.