MySQL Der in einer Fremdschlüsseleinschränkung erforderliche Index kann nicht gelöscht werden


155

Ich muss meine vorhandene Datenbank ändern, um eine Spalte hinzuzufügen. Folglich möchte ich auch das Feld UNIQUE aktualisieren, um diese neue Spalte einzuschließen. Ich versuche, den aktuellen Index zu entfernen, erhalte aber weiterhin den FehlerMySQL 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

Angenommen UNIQUE KEY AIDauf mytable?
Mike Purcell

Antworten:


228

Sie müssen den Fremdschlüssel fallen lassen. Fremdschlüssel in MySQL erstellen automatisch einen Index für die Tabelle (es gab eine SO-Frage zum Thema).

ALTER TABLE mytable DROP FOREIGN KEY mytable_ibfk_1 ; 

12
Möglicherweise möchten Sie es nach dem Löschen des Index wieder hinzufügen: ALTER TABLE mytableADD CONSTRAINT mytable_ibfk_1FOREIGN KEY ( AID) REFERENCES mytable_a( ID) ON DELETE CASCADE;
Laffuste

8
Das ist großartig, aber was kann ich tun, wenn meine FOREIGN KEYEinschränkung anonym war?
Pehat

@Pehat überprüfen Sie meine Antwort unten stackoverflow.com/a/54145440/2305119
thyzz

1
Hinweis: Der Fremdschlüssel ist möglicherweise nicht so offensichtlich. Um alle Fremdschlüssel zu finden, die sich auf eine Tabelle und eine Spalte beziehen, können Sie diese Abfrage verwenden: dba.stackexchange.com/questions/102371/…
charlax

84

Schritt 1

Fremdschlüssel auflisten (HINWEIS, dass er sich vom Indexnamen unterscheidet)

SHOW CREATE TABLE  <Table Name>

Das Ergebnis zeigt Ihnen den Fremdschlüsselnamen.

Format:

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

Schritt 2

Drop-Schlüssel (Fremd / Primär / Schlüssel)

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

Schritt 3

Löschen Sie den Index.


18

Wenn Sie meinen, dass Sie dies tun können:

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.

Aber dann:

ALTER TABLE mytable
DROP KEY AID ;

gibt Fehler.


Sie können den Index löschen und einen neuen in einer ALTER TABLEAnweisung erstellen :

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

8

Da Sie einen Index für ein Fremdschlüsselfeld haben müssen, können Sie einfach einen einfachen Index für das Feld 'AID' erstellen.

CREATE INDEX aid_index ON mytable (AID);

und erst dann den eindeutigen Index 'AID' löschen

ALTER TABLE mytable DROP INDEX AID;

7

Ein Fremdschlüssel erfordert immer einen Index. Ohne einen Index, der die Einschränkung erzwingt, wäre für jeden eingefügten oder aktualisierten Schlüssel in der Referenzierungstabelle ein vollständiger Tabellenscan in der referenzierten Tabelle erforderlich. Und das hätte inakzeptable Auswirkungen auf die Leistung. Dies hat die folgenden 2 Konsequenzen:

  • Beim Erstellen eines Fremdschlüssels prüft die Datenbank, ob ein Index vorhanden ist. Wenn nicht, wird ein Index erstellt. Standardmäßig hat es denselben Namen wie die Einschränkung.
  • Wenn nur ein Index für den Fremdschlüssel verwendet werden kann, kann er nicht gelöscht werden. Wenn Sie es wirklich nicht löschen möchten, müssen Sie entweder die Fremdschlüsseleinschränkung löschen oder zuerst einen anderen Index dafür erstellen.

1
Sie haben die Theorie, dass andere Antworten fehlten.
Dennis

1
Also: Wenn Sie einen zusammengesetzten eindeutigen Index haben (mehrere Spalten in einer eindeutigen Einschränkung), können Sie den eindeutigen AB-Schlüssel nur entfernen, wenn Sie einen Index für A und B haben. Wenn Sie diesen Fehler erhalten, verwendet eine andere Tabelle den Index der Spalte A oder B, und Sie müssen diese hinzufügen, bevor Sie das AB-Unikat sicher entfernen können.
Robin De Schepper

@RobinDeSchepper Gute Bemerkung. Bei Verwendung zusammengesetzter eindeutiger Indizes ist die Reihenfolge der Felder für den eindeutigen Index nicht wichtig, für einen Fremdschlüssel jedoch möglicherweise. Ein eindeutiger Index für A, B kann von einem Fremdschlüssel für A verwendet werden, nicht jedoch von einem Fremdschlüssel für B.
Stefan Mondelaers

2

Ich denke, dies ist eine einfache Möglichkeit, den Index zu löschen.

set FOREIGN_KEY_CHECKS=1;

ALTER TABLE mytable DROP INDEX AID;

set FOREIGN_KEY_CHECKS=0;

2
Ich denke, Sie haben das Aktivieren und Deaktivieren der Schecks ausgetauscht. Oben würde ich erwarten FOREIGN_KEY_CHEK=0und am Ende FOREIGN_KEY_CHEK=1.
Romor

0

In meinem Fall habe ich den Fremdschlüssel gelöscht und konnte den Index immer noch nicht löschen. Das lag daran, dass es in denselben Feldern noch eine andere Tabelle gab, die einen Fremdschlüssel für diese Tabelle hatte. Nachdem ich den Fremdschlüssel in der anderen Tabelle gelöscht hatte, konnte ich die Indizes in dieser Tabelle löschen.


0

Wenn Sie eine Fremdschlüsselspalte löschen möchten (wenn Sie eine Einschränkung haben), sollten Sie zuerst den Fremdschlüssel und dann die Spalte löschen. Wenn Sie den Fremdschlüssel löschen, müssen Sie nicht den gesamten Namen übergeben, sondern nur den Fremdschlüssel Spaltenname:

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

Weitere Details zu:

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.