MySQL ไม่สามารถวางดัชนีที่ต้องการในข้อ จำกัด foreign key


156

ฉันต้องแก้ไขฐานข้อมูลที่มีอยู่ของฉันเพื่อเพิ่มคอลัมน์ ดังนั้นฉันต้องการอัปเดตฟิลด์ UNIQUE เพื่อรวมคอลัมน์ใหม่นั้น ฉันกำลังพยายามลบดัชนีปัจจุบัน แต่ได้รับข้อผิดพลาดต่อไปMySQL Cannot drop index needed in a foreign key constraint

CREATE TABLE mytable_a (
ID          TINYINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Name        VARCHAR(255) NOT NULL,
UNIQUE(Name)
) ENGINE=InnoDB;

CREATE TABLE mytable_b (
ID          TINYINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Name        VARCHAR(255) NOT NULL,
UNIQUE(Name)
) ENGINE=InnoDB;

CREATE TABLE mytable_c (
ID          TINYINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Name        VARCHAR(255) NOT NULL,
UNIQUE(Name)
) ENGINE=InnoDB;


CREATE TABLE `mytable` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `AID` tinyint(5) NOT NULL,
  `BID` tinyint(5) NOT NULL,
  `CID` tinyint(5) NOT NULL,
  PRIMARY KEY (`ID`),
  UNIQUE KEY `AID` (`AID`,`BID`,`CID`),
  KEY `BID` (`BID`),
  KEY `CID` (`CID`),
  CONSTRAINT `mytable_ibfk_1` FOREIGN KEY (`AID`) REFERENCES `mytable_a` (`ID`) ON DELETE CASCADE,
  CONSTRAINT `mytable_ibfk_2` FOREIGN KEY (`BID`) REFERENCES `mytable_b` (`ID`) ON DELETE CASCADE,
  CONSTRAINT `mytable_ibfk_3` FOREIGN KEY (`CID`) REFERENCES `mytable_c` (`ID`) ON DELETE CASCADE
) ENGINE=InnoDB;




mysql> ALTER TABLE mytable DROP INDEX AID;
ERROR 1553 (HY000): Cannot drop index 'AID': needed in a foreign key constraint

สมมติUNIQUE KEY AIDบน mytable?
Mike Purcell

คำตอบ:


228

คุณต้องวางรหัสต่างประเทศ คีย์ต่างประเทศใน MySQL สร้างดัชนีบนตารางโดยอัตโนมัติ (มีคำถาม SOในหัวข้อ)

ALTER TABLE mytable DROP FOREIGN KEY mytable_ibfk_1 ; 

12
คุณอาจต้องการที่จะเพิ่มกลับมาหลังจากวางดัชนี: ALTER TABLE mytableเพิ่ม ADD CONSTRAINT mytable_ibfk_1KEY ( AID) การอ้างอิงmytable_a( ID) การอ้างอิง( ) ON DELETE CASCADE;
laffuste

8
เยี่ยมมาก แต่ฉันควรทำอย่างไรหากFOREIGN KEYข้อ จำกัดของฉันไม่ระบุชื่อ
Pehat

@ ตรวจสอบคำตอบของฉันด้านล่างstackoverflow.com/a/54145440/2305119
thyzz

1
หมายเหตุ: รหัสต่างประเทศอาจไม่ชัดเจน หากต้องการค้นหากุญแจต่างประเทศทั้งหมดที่เกี่ยวข้องกับตารางและคอลัมน์คุณสามารถใช้แบบสอบถามนี้: dba.stackexchange.com/questions/102371/…
charlax

84

ขั้นตอนที่ 1

แสดงรายการ foreign key (โปรดทราบว่าต่างจากชื่อดัชนี)

SHOW CREATE TABLE  <Table Name>

ผลลัพธ์จะแสดงชื่อคีย์ต่างประเทศให้คุณ

รูปแบบ:

CONSTRAINT `FOREIGN_KEY_NAME` FOREIGN KEY (`FOREIGN_KEY_COLUMN`) REFERENCES `FOREIGN_KEY_TABLE` (`id`),

ขั้นตอนที่ 2

คีย์ดร็อป (ต่างประเทศ / หลัก / คีย์)

ALTER TABLE <Table Name> DROP FOREIGN KEY <Foreign key name>

ขั้นตอนที่ 3

วางดัชนี


18

หากคุณหมายความว่าคุณสามารถทำได้:

CREATE TABLE mytable_d (
ID          TINYINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Name        VARCHAR(255) NOT NULL,
UNIQUE(Name)
) ENGINE=InnoDB;


ALTER TABLE mytable
ADD COLUMN DID tinyint(5) NOT NULL,
ADD CONSTRAINT mytable_ibfk_4 
      FOREIGN KEY (DID) 
        REFERENCES mytable_d (ID) ON DELETE CASCADE;

 > OK.

แต่แล้ว:

ALTER TABLE mytable
DROP KEY AID ;

ให้ข้อผิดพลาด


คุณสามารถวางดัชนีและสร้างดัชนีใหม่ในหนึ่งALTER TABLEคำสั่ง:

ALTER TABLE mytable
DROP KEY AID ,
ADD UNIQUE KEY AID (AID, BID, CID, DID);

8

เนื่องจากคุณต้องมีดัชนีในเขตข้อมูลคีย์ต่างประเทศคุณสามารถสร้างดัชนีอย่างง่ายบนฟิลด์ 'AID'

CREATE INDEX aid_index ON mytable (AID);

และจากนั้นปล่อยดัชนีเฉพาะ 'AID'

ALTER TABLE mytable DROP INDEX AID;

7

foreign key ต้องใช้ดัชนีเสมอ หากไม่มีดัชนีที่บังคับใช้ข้อ จำกัด จะต้องใช้การสแกนแบบเต็มตารางบนตารางที่อ้างอิงสำหรับทุกคีย์ที่แทรกหรืออัพเดตในตารางอ้างอิง และนั่นจะมีผลกระทบต่อประสิทธิภาพที่ยอมรับไม่ได้ สิ่งนี้มีผลที่ตามมา 2 ประการ:

  • เมื่อสร้าง foreign key ฐานข้อมูลจะตรวจสอบว่ามีดัชนีอยู่หรือไม่ หากไม่มีดัชนีจะถูกสร้างขึ้น โดยค่าเริ่มต้นมันจะมีชื่อเดียวกับข้อ จำกัด
  • เมื่อมีดัชนีเพียงหนึ่งดัชนีเท่านั้นที่สามารถใช้สำหรับคีย์ต่างประเทศจะไม่สามารถลดลงได้ หากคุณไม่ต้องการวางคุณต้องวางข้อ จำกัด foreign key หรือสร้างดัชนีอื่นก่อน

1
คุณมีทฤษฎีที่ไม่มีคำตอบอื่น ๆ
เดนนิส

1
ดังนั้น: หากคุณมีดัชนีที่ไม่ซ้ำกันแบบผสม (หลายคอลัมน์ในข้อ จำกัด ที่ไม่ซ้ำกัน) คุณไม่สามารถลบคีย์ AB ที่ไม่ซ้ำได้นอกจากว่าคุณมีดัชนีสำหรับ A และ B หากคุณได้รับข้อผิดพลาดนี้ตารางอื่นกำลังใช้ดัชนีของคอลัมน์ A หรือ B และคุณจะต้องเพิ่มรายการเหล่านั้นก่อนจึงจะสามารถลบ AB ที่ไม่ซ้ำได้อย่างปลอดภัย
Robin De Schepper

@RobinDeSchepper คำพูดดี ๆ และเมื่อใช้ดัชนีที่ไม่ซ้ำกันแบบผสมลำดับของฟิลด์ไม่สำคัญสำหรับดัชนีที่ไม่ซ้ำกัน แต่มันอาจสำคัญสำหรับ foreign key ดัชนีที่เป็นเอกลักษณ์ของ A, B สามารถใช้โดย foreign key บน A แต่ไม่ใช่โดย foreign key บน B
Stefan Mondelaers

2

ฉันคิดว่านี่เป็นวิธีที่ง่ายในการทำดัชนี

set FOREIGN_KEY_CHECKS=1;

ALTER TABLE mytable DROP INDEX AID;

set FOREIGN_KEY_CHECKS=0;

2
ฉันคิดว่าคุณแลกเปลี่ยนการเปิดใช้งานและปิดการใช้งานการตรวจสอบ ที่ด้านบนผมจะคาดหวังและในตอนท้ายFOREIGN_KEY_CHEK=0 FOREIGN_KEY_CHEK=1
romor

0

ในกรณีของฉันฉันลบรหัสต่างประเทศและฉันก็ยังไม่สามารถวางดัชนีได้ นั่นเป็นเพราะยังมีตารางอื่นที่มีรหัสต่างประเทศในตารางนี้ในเขตข้อมูลเดียวกัน หลังจากฉันลบรหัสต่างประเทศในตารางอื่นฉันสามารถวางดัชนีในตารางนี้ได้


0

หากคุณต้องการวางคอลัมน์กุญแจต่างประเทศ (แม่มดมีข้อ จำกัด ) คุณควรวางกุญแจต่างประเทศก่อนจากนั้นจึงวางคอลัมน์เมื่อคุณวางกุญแจต่างประเทศคุณไม่จำเป็นต้องผ่านชื่อทั้งหมดเพียงแค่ผ่านกุญแจต่างประเทศ ชื่อคอลัมน์:

$table->dropForeign(['currency_id']);
$table->dropColumn('currency_id');

รายละเอียดเพิ่มเติมเกี่ยวกับ:

https://laravel.com/docs/6.x/migrations#foreign-key-constraints

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