MySQL Tidak dapat menjatuhkan indeks yang diperlukan dalam batasan kunci asing


155

Saya perlu mengubah database saya yang ada untuk menambahkan kolom. Karenanya saya juga ingin memperbarui bidang UNIQUE untuk mencakup kolom baru itu. Saya mencoba untuk menghapus indeks saat ini tetapi tetap mendapatkan kesalahanMySQL 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

Dengan asumsi UNIQUE KEY AIDpada mytable?
Mike Purcell

Jawaban:


228

Anda harus menjatuhkan kunci asing. Kunci asing di MySQL secara otomatis membuat indeks di atas meja (Ada pertanyaan SO pada topik).

ALTER TABLE mytable DROP FOREIGN KEY mytable_ibfk_1 ; 

12
Anda mungkin ingin menambahkannya kembali setelah menjatuhkan indeks: ALTER TABLE mytableADD CONSTRAINT mytable_ibfk_1FOREIGN KEY ( AID) REFERENSI mytable_a( ID) PADA DELETE CASCADE;
laffuste

8
Itu hebat, tetapi apa yang bisa saya lakukan jika FOREIGN KEYkendala saya anonim?
Pehat

@Pehat periksa jawaban saya di bawah stackoverflow.com/a/54145440/2305119
thyzz

1
Catatan: kunci asing mungkin tidak sejelas ini. Untuk menemukan semua kunci asing yang terkait dengan tabel dan kolom, Anda dapat menggunakan kueri ini: dba.stackexchange.com/questions/102371/…
charlax

84

Langkah 1

Daftar kunci asing (CATATAN yang berbeda dengan nama indeks)

SHOW CREATE TABLE  <Table Name>

Hasilnya akan menunjukkan kepada Anda nama kunci asing.

Format:

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

Langkah 2

Kunci Drop (Asing / primer / kunci)

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

Langkah 3

Jatuhkan indeks.


18

Jika Anda bermaksud melakukan ini:

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.

Tapi kemudian:

ALTER TABLE mytable
DROP KEY AID ;

memberi kesalahan.


Anda dapat menjatuhkan indeks dan membuat yang baru dalam satu ALTER TABLEpernyataan:

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

8

Karena Anda harus memiliki indeks pada bidang kunci asing, Anda cukup membuat indeks sederhana di bidang 'AID'

CREATE INDEX aid_index ON mytable (AID);

dan hanya kemudian menjatuhkan indeks unik 'AID'

ALTER TABLE mytable DROP INDEX AID;

7

Kunci asing selalu membutuhkan indeks. Tanpa indeks yang menegakkan kendala akan membutuhkan pemindaian tabel penuh pada tabel referensi untuk setiap kunci yang dimasukkan atau diperbarui dalam tabel referensi. Dan itu akan memiliki dampak kinerja yang tidak dapat diterima. Ini memiliki 2 konsekuensi sebagai berikut:

  • Saat membuat kunci asing, database memeriksa apakah ada indeks. Jika tidak, indeks akan dibuat. Secara default, itu akan memiliki nama yang sama dengan kendala.
  • Ketika hanya ada satu indeks yang dapat digunakan untuk kunci asing, itu tidak bisa dijatuhkan. Jika Anda benar-benar tidak ingin menjatuhkannya, Anda harus menghapus batasan kunci asing atau membuat indeks lain terlebih dahulu.

1
Anda memiliki teori yang tidak dimiliki jawaban lain.
Dennis

1
Jadi: Jika Anda memiliki indeks unik majemuk (beberapa kolom dalam batasan unik), Anda tidak dapat menghapus kunci AB unik kecuali jika Anda memiliki indeks untuk A dan B. Jika Anda mendapatkan kesalahan ini, tabel lain menggunakan indeks kolom A atau B, dan Anda harus menambahkannya sebelum Anda dapat menghapus unik AB dengan aman.
Robin De Schepper

@RobinDeSchepper Ucapan baik. Dan ketika menggunakan indeks unik majemuk, urutan bidang tidak penting untuk indeks unik, tetapi mungkin penting untuk kunci asing. Indeks unik pada A, B dapat digunakan oleh kunci asing di A, tetapi tidak oleh kunci asing di B.
Stefan Mondelaers

2

Saya pikir ini cara mudah untuk menjatuhkan indeks.

set FOREIGN_KEY_CHECKS=1;

ALTER TABLE mytable DROP INDEX AID;

set FOREIGN_KEY_CHECKS=0;

2
Saya pikir Anda bertukar mengaktifkan dan menonaktifkan cek. Di atas saya harapkan FOREIGN_KEY_CHEK=0dan pada akhirnya FOREIGN_KEY_CHEK=1.
romor

0

Dalam kasus saya, saya menjatuhkan kunci asing dan saya masih tidak bisa menjatuhkan indeks. Itu karena ada meja lain yang memiliki kunci asing untuk tabel ini di bidang yang sama. Setelah saya menjatuhkan kunci asing di meja lain saya bisa menjatuhkan indeks di tabel ini.


0

jika Anda ingin menjatuhkan kolom kunci Asing (penyihir memegang batasan) Anda harus menjatuhkan kunci asing terlebih dahulu kemudian menjatuhkan kolom, ketika Anda menjatuhkan kunci asing, Anda tidak harus melewati semua nama, cukup lewat kunci Asing nama kolom:

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

lebih detail tentang:

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.