ข้อ จำกัด คีย์ต่างประเทศผิดพลาดล้มเหลว


110

ฉันได้รับข้อความแสดงข้อผิดพลาดนี้:

ข้อผิดพลาด 1217 (23000) ที่บรรทัด 40: ไม่สามารถลบหรืออัปเดตแถวหลัก: ข้อ จำกัด ของคีย์ภายนอกล้มเหลว

... เมื่อฉันพยายามวางโต๊ะ:

DROP TABLE IF EXISTS `area`;

... กำหนดไว้เช่นนี้:

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;

สิ่งที่ตลกคือฉันทิ้งตารางอื่น ๆ ทั้งหมดในสคีมาที่มีคีย์ต่างประเทศareaอยู่แล้ว จริงๆแล้วฐานข้อมูลว่างเปล่ายกเว้นareaตาราง

มันจะมีแถวลูกได้อย่างไรหากไม่มีวัตถุอื่นในฐานข้อมูล เท่าที่ฉันรู้ InnoDB ไม่อนุญาตให้ใช้คีย์ต่างประเทศในสคีมาอื่นใช่หรือไม่

(ฉันสามารถเรียกใช้RENAME TABLE area TO something_elseคำสั่ง: -?)


เป็นไปได้ไหมว่าตารางเป็นส่วนหนึ่งของความสัมพันธ์ Referential-Integrity ในสคีมาอื่น
Raj More

ฉันมีสำเนาอื่น ๆ ของแอปดังนั้นจึงเป็นไปได้เสมอ อย่างไรก็ตามไวยากรณ์ที่ฉันใช้นั้นเป็นพื้นฐานCONSTRAINT fk_servicio_area1 FOREIGN KEY (area_id) REFERENCES area (area_id)กล่าวคือไม่มีชื่อสคีมาในการอ้างอิงตาราง: -?
ÁlvaroGonzález

คำตอบ:


101

ความเป็นไปได้สองประการ:

  1. มีตารางภายในสคีมาอื่น ("ฐานข้อมูล" ในคำศัพท์ mysql) ซึ่งมีการอ้างอิง FK
  2. พจนานุกรมข้อมูลภายในของ innodb ไม่ซิงค์กับ mysql one

คุณสามารถดูตารางว่าเป็นตารางใด (หนึ่งในนั้น) โดยทำ "แสดงสถานะเครื่องยนต์ INNODB" หลังจากที่ล้มเหลว

หากปรากฎว่าเป็นกรณีหลังฉันจะถ่ายโอนข้อมูลและกู้คืนเซิร์ฟเวอร์ทั้งหมดหากทำได้

MySQL 5.1 ขึ้นไปจะให้ชื่อตารางที่มี FK ในข้อความแสดงข้อผิดพลาด


1
ฉันไม่สามารถทำให้เกิดปัญหาอีกต่อไป พจนานุกรมไม่ซิงค์มีความโดดเด่นเป็นเหตุผลที่เป็นไปได้ ฉันจะทดสอบทุกวันและดูว่ามีSHOW ENGINE INNODB STATUSรายงานอะไรบ้าง
ÁlvaroGonzález

3
ขอบคุณสำหรับคำตอบนี้! ฉันมีตารางแบบหลายต่อกลุ่มที่ยังคงอ้างอิงตารางที่เราวางไม่ได้ดังนั้นฉันจึงต้องวางโต๊ะนั้นก่อน
Christian Oudard

5
สถานะ INNODB ของเครื่องยนต์แสดงรายการข้อผิดพลาดคีย์ต่างประเทศสุดท้ายภายใต้ "ข้อผิดพลาดของคีย์ต่างประเทศล่าสุด" มีการประทับเวลา
bbrame

อาจมีตารางที่ยังมีคีย์อ้างอิงไปยังตารางหัวเรื่อง ในกรณีของฉันเช่นนี้
RT

ประหยัดเวลาได้มาก ทิ้งฐานข้อมูลภายใต้ "LATEST FOREIGN KEY ERROR"
Sand1512

121

ตามคำเรียกร้องตอนนี้เป็นคำตอบ ...

เมื่อใช้ MySQL Query Browser หรือ phpMyAdmin ดูเหมือนว่ามีการเปิดการเชื่อมต่อใหม่สำหรับแต่ละแบบสอบถาม ( bugs.mysql.com/bug.php?id=8280 ) ทำให้จำเป็นต้องเขียนคำสั่ง drop ทั้งหมดในแบบสอบถามเดียวเช่น

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ทำหน้าที่เป็นมาตรการรักษาความปลอดภัยเพิ่มเติม ...


2
สำหรับผู้ที่สร้างดัมพ์โดยใช้ phpMyAdmin มีตัวเลือก "ปิดใช้งานการตรวจสอบคีย์ต่างประเทศ" ที่จะเพิ่มSET FOREIGN_KEY_CHECKS=0;ไปยังจุดเริ่มต้นของดัมพ์โดยอัตโนมัติ
Mike

ดูเหมือนว่า phpMyAdmin ได้ใช้คุณสมบัติที่น่ารักนี้แล้วตอนนี้ฉันกำลังรอให้ mysqlWorkbench ทำเช่นเดียวกัน! :)
Karlis Rode

@CodeMed FYI ฉันยอมรับคำตอบของ MarkR เพราะมันให้คำอธิบายสำหรับปัญหาที่สมเหตุสมผล - แม้ว่าฉันจะยอมรับว่าฉันไม่สามารถตรวจสอบได้เนื่องจากฉันไม่ได้เผชิญกับปัญหาเดียวกันนี้ใน 6 ปีต่อ ๆ ไปแม้แต่ครั้งเดียว คำตอบนี้และก่อนหน้านี้เป็นวิธีแก้ปัญหา (ดีสำหรับสิ่งนั้น) แต่ไม่ได้ตอบคำถามด้วยตัวเองจริงๆและเนื่องจากคุณสามารถยอมรับคำตอบเดียวที่ฉันต้องเลือก
ÁlvaroGonzález

1
คำเตือน:นี่ไม่ใช่วิธีแก้ปัญหา แต่เป็นวิธีแก้ปัญหาของคนขี้เกียจเท่านั้น หลังจากใช้สิ่งนี้ (โดยมีบันทึกในตารางอื่น ๆ ที่ชี้ไปที่ตารางที่ตกหล่น) คุณจะพบว่ามีคีย์แปลกปลอมห้อยซึ่งทำลายความสอดคล้อง ( Cในกรด ) ของฐานข้อมูลของคุณและแอปพลิเคชันของคุณจะเริ่มทิ้งข้อยกเว้นไปทั่วทุกที่ คุณได้รับการเตือนแล้ว
bekce

แม้ว่าฉันแน่ใจว่าคำเตือนของ bekce ควรเข้าใจและเอาใจใส่ แต่วิธีนี้ใช้ได้ผลกับฉันในสถานการณ์ที่ฉันมั่นใจว่าฉันทิ้งตารางทั้งหมดที่ชี้ไปยังตารางด้วยข้อ จำกัด ของคีย์ต่างประเทศที่ยุ่งยาก
user1147171

47

ปิดใช้งานการตรวจสอบคีย์ต่างประเทศ

SET FOREIGN_KEY_CHECKS=0

62
คำสั่งที่ถูกต้องดูเหมือนจะเป็นSET FOREIGN_KEY_CHECKS=0และจะแก้ไขข้อความแสดงข้อผิดพลาด คุณมีความคิดว่าเหตุใดจึงจำเป็นต้องใช้สิ่งนี้? คีย์ต่างประเทศถูกแคชแม้ว่าตารางจะหายไปหรือไม่?
ÁlvaroGonzález

1
พูดตามจริงฉันไม่รู้ว่าทำไมถึงเกิดปัญหาดังกล่าวขึ้น แต่อย่าลืมปิดการตรวจสอบคีย์ทุกครั้งที่คุณทำการเปลี่ยนแปลงหรืออัปเดตครั้งใหญ่ มันเคยเกิดขึ้นกับฉันหลายครั้งทำให้ฉันนอนไม่หลับมาหลายวัน
Flakron Bytyqi

55
อย่าลืมทำSET FOREIGN_KEY_CHECKS=1;หลังจากทำเสร็จแล้ว!
pedro_sland

5
เมื่อใช้ MySQL Query Browser หรือ phpMyAdmin ดูเหมือนว่ามีการเปิดการเชื่อมต่อใหม่สำหรับแต่ละแบบสอบถาม ( bugs.mysql.com/bug.php?id=8280 ) ทำให้จำเป็นต้องเขียนคำสั่ง drop ทั้งหมดในแบบสอบถามเดียวเช่น 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 ทำหน้าที่เป็นมาตรการรักษาความปลอดภัยเพิ่มเติม ...
Karlis Rode

1
@KarlisRode, Bravo สำหรับความคิดเห็นบน phpMyAdmin ถ้าคุณจะใส่เป็นคำตอบฉันจะ +1 ให้
Sablefoste

28

จากบล็อกนี้ :

คุณสามารถปิดใช้งานการตรวจสอบคีย์ต่างประเทศชั่วคราว:

SET FOREIGN_KEY_CHECKS=0;

อย่าลืมกู้คืนเมื่อคุณทำเสร็จแล้ว:

SET FOREIGN_KEY_CHECKS=1;

คำตอบที่ดีเพราะฉันกำลังพัฒนาในท้องถิ่น :)
Adelin

เป็นวิธีแก้ปัญหาที่ถูกต้อง (ฉันสามารถยืนยันได้ว่าใช้งานได้) แต่รายการบล็อกที่เชื่อมโยงไม่ได้พูดถึงสถานการณ์ในคำถามนี้จริงๆ (ฐานข้อมูลที่ว่างเปล่าบันทึกไว้แล้วสำหรับหนึ่งตาราง)
ÁlvaroGonzález

6

หวังว่าจะได้ผล

ตั้งค่า Foreign_key_checks = 0; วางตารางtable name; SET Foreign_key_checks = 1;


ใช่มันใช้งานได้ตามที่เคยกล่าวไว้ก่อนหน้านี้หลายครั้ง ;-)
ÁlvaroGonzález

1

บน Rails คุณสามารถทำสิ่งต่อไปนี้ได้โดยใช้rails console:

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

0

บางทีคุณอาจได้รับข้อผิดพลาดเมื่อทำงานกับตารางนี้มาก่อน คุณสามารถเปลี่ยนชื่อตารางและลองลบอีกครั้ง

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

0

ฉันพบวิธีแก้ปัญหาง่ายๆส่งออกฐานข้อมูลแก้ไขสิ่งที่คุณต้องการแก้ไขในโปรแกรมแก้ไขข้อความแล้วนำเข้า เสร็จแล้ว


4
นั่นเป็นวิธีแก้ปัญหาที่น่าสนใจซึ่งอาจไม่ควรเกิดขึ้นจริง สิ่งที่ต้องเปลี่ยนแปลงควรทำผ่าน DBMS แทน การแก้ไขการถ่ายโอนข้อมูลฐานข้อมูลในโปรแกรมแก้ไขข้อความดูเหมือนเป็นหนทางที่สุกงอมสำหรับปัญหา
Brandon Anzaldi

1
ฉันไม่เข้าใจจริงๆว่าคุณเป็นอะไร การทิ้งฐานข้อมูลลบCREATE TABLEโค้ดและโหลดการถ่ายโอนข้อมูลอีกครั้ง ... จะไม่ทำให้ MySQL ลบตาราง และถ้าคุณหมายถึงการกู้คืนการถ่ายโอนข้อมูลในฐานข้อมูลใหม่ ... หากคุณต้องการล้างตารางทั้งหมดเช่นฉันฐานข้อมูลที่สร้างขึ้นใหม่จะว่างเปล่า หากคุณต้องการเก็บตารางSET FOREIGN_KEY_CHECKS=0ไว้วิธีแก้ปัญหาที่กล่าวถึงทุกที่ในที่นี้ใช้งานได้ดีและง่ายกว่า และคุณอาจไม่จำเป็นต้องแก้ไขดัมพ์อีกต่อไปเนื่องจากสำเนาข้อมูลใหม่ของคุณอาจไม่มีพจนานุกรมข้อมูลที่ไม่ซิงค์
ÁlvaroGonzález

-1

ไม่สามารถลบหรืออัปเดตแถวหลัก: ข้อ จำกัด ของคีย์ภายนอกล้มเหลว ( table1. user_role, CONSTRAINT FK143BF46A8dsfsfds@#5A6BD60FOREIGN KEY ( user_id) REFERENCES user( id))

สิ่งที่ฉันทำในสองขั้นตอนง่ายๆ ก่อนอื่นฉันจะลบแถวลูกในตารางลูกเช่น

mysql> ลบออกจาก table2 โดยที่ role_id = 2 && user_id = 20;

Query OK 1 แถวได้รับผลกระทบ (0.10 วินาที)

และขั้นตอนที่สองเป็นการลบพาเรนต์

ลบจาก table1 โดยที่ id = 20;

Query OK 1 แถวได้รับผลกระทบ (0.12 วินาที)

ด้วยเหตุนี้ฉันจึงแก้ปัญหาซึ่งหมายถึง Delete Child จากนั้น Delete parent

ฉันหวังว่าคุณจะได้รับมัน :)


โปรดอ่านคำถามอีกครั้ง คุณไม่สามารถลบตารางที่ไม่มีอยู่
ÁlvaroGonzález

ในสถานการณ์นี้เราสามารถลบข้อ จำกัด ของคีย์ต่างประเทศจากนั้นลองลบตาราง เราสามารถวางคีย์ต่างประเทศเช่น ALTER TABLE <TABLE_NAME> DROP CONSTRAINT <FOREIGN_KEY_NAME>
Aadil Masavir
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.