Sahte yabancı anahtar kısıtlaması başarısız


110

Bu hata mesajını alıyorum:

40. satırdaki ERROR 1217 (23000): Bir üst satır silinemez veya güncellenemez: yabancı anahtar kısıtlaması başarısız olur

... masayı düşürmeye çalıştığımda:

DROP TABLE IF EXISTS `area`;

... şu şekilde tanımlanmıştır:

CREATE TABLE `area` (
  `area_id` char(3) COLLATE utf8_spanish_ci NOT NULL,
  `nombre_area` varchar(30) COLLATE utf8_spanish_ci NOT NULL,
  `descripcion_area` varchar(100) COLLATE utf8_spanish_ci NOT NULL,
  PRIMARY KEY (`area_id`),
  UNIQUE KEY `nombre_area_UNIQUE` (`nombre_area`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;

Komik olan, şemadaki yabancı anahtarlara karşı olan diğer tüm tabloları zaten düşürmüş olmamarea . Aslında, areatablo dışında veritabanı boş .

Veritabanında başka nesne yoksa nasıl alt satırlara sahip olabilir? Bildiğim kadarıyla InnoDB diğer şemalarda yabancı anahtarlara izin vermiyor, değil mi?

(Bir RENAME TABLE area TO something_elsekomutu bile çalıştırabilirim : -?)


Tablonun başka bir şemadaki Referans-Bütünlük ilişkisinin bir parçası olması mümkün mü?
Raj More

Uygulamanın başka kopyalarına sahibim, bu yüzden her zaman mümkün. Bununla birlikte, kullandığım sözdizimi temelde CONSTRAINT fk_servicio_area1 FOREIGN KEY (area_id) REFERENCES area (area_id), yani tablo başvurusunda şema adı yok: -?
Álvaro González

Yanıtlar:


101

İki olasılık:

  1. FK referansı olan başka bir şema içinde (mysql terminolojisinde "veritabanı") bir tablo var
  2. Innodb dahili veri sözlüğü mysql one ile uyumlu değil.

Bırakma başarısız olduktan sonra "SHOW ENGINE INNODB STATUS" yaparak hangi tablo olduğunu (bunlardan biri) görebilirsiniz.

İkinci durum ortaya çıkarsa, yapabiliyorsanız tüm sunucuyu döküp geri yüklerim.

MySQL 5.1 ve üzeri, hata mesajında ​​FK ile birlikte tablonun adını verecektir.


1
Artık sorunu yeniden oluşturamıyorum. Senkronize olmayan sözlük, olası bir neden olarak öne çıkıyor. Bunu gün test edeceğim ve hangi SHOW ENGINE INNODB STATUSraporları göreceğim .
Álvaro González

3
Bu cevap için teşekkürler! Hâlâ düşemediğimiz tabloyu referans alan çoktan çoğa bir tablom vardı, bu yüzden önce o tabloyu düşürmek zorunda kaldım.
Christian Oudard

5
MOTORU INNODB DURUMUNU GÖSTER "EN SON YABANCI ANAHTAR HATASI" altında son yabancı anahtar hatasını listeler. Bunun bir zaman damgası var.
bbrame

hala konu tablosuna referans anahtarı olan bir tablo olabilir. benim durumumdaydı, bunun gibi.
RT

Çok zaman kazandım. Db "EN SON YABANCI ANAHTAR HATASI" altına düştü
Sand1512

121

Talep üzerine, şimdi bir cevap olarak ...

MySQL Sorgu Tarayıcısını veya phpMyAdmin'i kullanırken, her sorgu için yeni bir bağlantı açıldığı görülür ( bugs.mysql.com/bug.php?id=8280 ), bu da tüm bırakma ifadelerinin tek bir sorguya yazılmasını gerekli kılar , örn.

SET FOREIGN_KEY_CHECKS=0; 
DROP TABLE my_first_table_to_drop; 
DROP TABLE my_second_table_to_drop; 
SET FOREIGN_KEY_CHECKS=1; 

Nerede SET FOREIGN_KEY_CHECKS=1bir ek güvenlik önlemi olarak hizmet vermektedir ...


2
PhpMyAdmin kullanarak bir döküm oluşturanlar için, dökümün SET FOREIGN_KEY_CHECKS=0;başlangıcına otomatik olarak eklenecek bir "Yabancı anahtar kontrollerini devre dışı bırak" seçeneği vardır .
Mike

Görünüşe göre phpMyAdmin bu güzel özelliği uyguladı, şimdi mysqlWorkbench'in de aynısını yapmasını bekliyorum! :)
Karlis Rode

@CodeMed Bilginize, MarkR'nin cevabını, mantıklı olan sorun için bir açıklama sağladığı için kabul ettim - yine de aynı sorunla sonraki 6 yılda, bir kez bile karşılaşmadığım için doğrulayamadığımı kabul ediyorum. Bu ve daha önceki cevaplar bir geçici çözüm sağlar (bunun için harika) ancak sorunun kendisine gerçekten hitap etmiyor ve sadece bir cevabı kabul edebileceğiniz için seçmek zorunda kaldım.
Álvaro González

1
Uyarı: Bu bir çözüm değil, yalnızca tembel adamın geçici çözümüdür. (Düştü tabloya işaret diğer bazı tabloları kayıtları ile) bu kullandıktan sonra, ölümcül tutarlılık (kırar yabancı anahtarları sarkan yaşayacaksınız C de ASİT veritabanınızın) ve uygulamalar her yerde istisnalar atmaya başlayacak. Uyarılmıştın.
bekce

Bekce'nin uyarısının anlaşılması ve dikkate alınması gerektiğinden emin olsam da, sorunlu yabancı anahtar kısıtlamaları olan tablolara işaret eden tüm tabloları da düşürdüğümden emin olduğum bir durumda bu çözüm benim için işe yaradı.
user1147171

47

Yabancı anahtar kontrolünü devre dışı bırakın

SET FOREIGN_KEY_CHECKS=0

62
Doğru komut görünüyor SET FOREIGN_KEY_CHECKS=0ve hata mesajını düzeltir. Bunun neden gerekli olduğu hakkında bir fikriniz var mı? Yabancı anahtarlar, tablolar gittikten sonra bile önbelleğe alınır mı?
Álvaro González

1
Doğruyu söylemek gerekirse, böyle bir sorunun neden ortaya çıktığı hakkında hiçbir fikrim yok, ancak her büyük değişiklik veya güncelleme yaptığınızda anahtar kontrolünü devre dışı bıraktığınızdan emin olun. Birkaç kez başıma geldi, beni günlerce uykusuz bıraktı.
Flakron Bytyqi

55
İşiniz SET FOREIGN_KEY_CHECKS=1;bittikten sonra emin olun !
pedro_sland

5
MySQL Sorgu Tarayıcısını veya phpMyAdmin'i kullanırken, her sorgu için yeni bir bağlantı açıldığı görülür ( bugs.mysql.com/bug.php?id=8280 ), bu da tüm bırakma ifadelerinin tek bir sorguya yazılmasını gerekli kılar , örn. SET FOREIGN_KEY_CHECKS=0; DROP TABLE my_first_table_to_drop; DROP TABLE my_second_table_to_drop; SET FOREIGN_KEY_CHECKS=1; SET FOREIGN_KEY_CHECKS = 1, ekstra bir güvenlik önlemi olarak hizmet ettiğinde ...
Karlis Rode

1
@KarlisRode, phpMyAdmin hakkındaki yorum için Bravo. Bunu yanıt olarak koyarsan, + 1'lerim.
Sablefoste

28

dan bu blog :

Yabancı anahtar kontrollerini geçici olarak devre dışı bırakabilirsiniz:

SET FOREIGN_KEY_CHECKS=0;

Sadece uğraşmayı bitirdikten sonra onları geri yüklediğinizden emin olun:

SET FOREIGN_KEY_CHECKS=1;


Bu geçerli bir çözümdür (çalıştığını doğrulayabilirim) ancak bağlantılı blog girişi bu sorudaki senaryo hakkında gerçekten konuşmuyor (bir tablo için zaten boş olan bir veritabanı).
Álvaro González

6

umarım işi

SET foreign_key_checks = 0; DAMLA TABLOSU table name; SET foreign_key_checks = 1;


Evet, daha önce defalarca bahsedildiği gibi işe yarıyor ;-)
Álvaro González

1

Rails üzerinde aşağıdakileri kullanarak aşağıdakileri yapabilirsiniz rails console:

connection = ActiveRecord::Base.connection
connection.execute("SET FOREIGN_KEY_CHECKS=0;")

0

Belki daha önce bu tabloyla çalışırken bir hata aldınız. Tabloyu yeniden adlandırabilir ve tekrar kaldırmayı deneyebilirsiniz.

ALTER TABLE `area` RENAME TO `area2`;
DROP TABLE IF EXISTS `area2`;

0

kolay bir çözüm buldum, veritabanını dışa aktartım, düzenlemek istediğiniz şeyi bir metin düzenleyicide düzenledikten sonra içe aktartım. Bitti


4
Bu ilginç bir çözüm, muhtemelen olmamalı. Bunun yerine, değiştirilmesi gereken her şey DBMS aracılığıyla yapılmalıdır. Bir metin düzenleyicide bir veritabanı dökümünü düzenlemek, sorunlar için olgun bir yol gibi görünüyor.
Brandon Anzaldi

1
Neyle uğraştığını gerçekten anlamıyorum. Veritabanını CREATE TABLEboşaltmak , kodu kaldırmak ve dökümü yeniden yüklemek ... MySQL'in tabloyu kaldırmasına neden olmaz. Ve eğer dökümü yeni bir veritabanına geri yüklemeyi kastediyorsanız ... Benim gibi tüm tabloları silmek istiyorsanız, yeni oluşturulan veritabanı zaten boş olacaktır. Bazı tabloları saklamak istiyorsanız, SET FOREIGN_KEY_CHECKS=0burada her yerde bahsedilen geçici çözüm iyi çalışıyor ve daha basittir; ve muhtemelen dökümü düzenlemenize gerek yoktur, çünkü verilerinizin yeni kopyası muhtemelen senkronize olmayan bir veri sözlüğüne sahip olmayacaktır.
Álvaro González

-1

Bir üst satır silinemez veya güncellenemez: yabancı anahtar kısıtlaması başarısız olur ( table1. user_role, CONSTRAINT FK143BF46A8dsfsfds@#5A6BD60FOREIGN KEY ( user_id) REFERENCES user( id))

İki basit adımda yaptığım şey. ilk olarak alt tablodaki alt satırı şöyle silerim:

mysql> rol_id = 2 && user_id = 20 olan tablo2'den sil

Sorgu TAMAM, 1 satır etkilendi (0,10 sn)

ve ikinci adımda ebeveynin silinmesi

id = 20 olan tablo1'den silin;

Sorgu TAMAM, 1 satır etkilendi (0,12 sn)

Bununla, Çocuğu Sil ve ardından Ebeveyni Sil anlamına gelen Sorunu çözüyorum.

Umarım almışsındır. :)


Lütfen soruyu tekrar okuyun. Var olmayan bir tabloyu kaldıramazsınız.
Álvaro González

bu senaryoda yabancı anahtar kısıtlamasını kaldırıp tabloyu silmeyi deneyebiliriz. Bu gibi yabancı anahtarı bırakabiliriz ALTER TABLE <TABLE_NAME> DROP CONSTRAINT <FOREIGN_KEY_NAME>
Aadil Masavir
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.