MySQL Nie można usunąć indeksu wymaganego w ograniczeniu klucza obcego

155

Muszę ZMIENIĆ moją istniejącą bazę danych, aby dodać kolumnę. W związku z tym chcę również zaktualizować pole UNIQUE, aby obejmowało tę nową kolumnę. Próbuję usunąć bieżący indeks, ale nadal pojawia się błądMySQL 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
user391986
źródło
Zakładając UNIQUE KEY AIDmytable?
Mike Purcell

Odpowiedzi:

228

Musisz upuścić klucz obcy. Klucze obce w MySQL automatycznie tworzą indeks w tabeli (było pytanie SO na ten temat).

ALTER TABLE mytable DROP FOREIGN KEY mytable_ibfk_1 ; 
Brian Fisher
źródło
12
Możesz chcieć dodać go z powrotem po usunięciu indeksu: ALTER TABLE mytableADD CONSTRAINT mytable_ibfk_1FOREIGN KEY ( AID) REFERENCES mytable_a( ID) ON DELETE CASCADE;
laffuste
8
To świetnie, ale co mogę zrobić, jeśli moje FOREIGN KEYograniczenie było anonimowe?
Pehat
@Pehat sprawdź moją odpowiedź poniżej stackoverflow.com/a/54145440/2305119
thyzz
1
Uwaga: klucz obcy może nie być tak oczywisty. Aby znaleźć wszystkie klucze obce związane z tabelą i kolumną, możesz użyć tego zapytania: dba.stackexchange.com/questions/102371/…
charlax
84

Krok 1

Lista kluczy obcych (UWAGA, różni się od nazwy indeksu)

SHOW CREATE TABLE  <Table Name>

Wynik pokaże nazwę klucza obcego.

Format:

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

Krok 2

Upuść (obcy / podstawowy / klucz)

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

Krok 3

Upuść indeks.

Abhishek Goel
źródło
18

Jeśli masz na myśli, że możesz to zrobić:

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.

Ale wtedy:

ALTER TABLE mytable
DROP KEY AID ;

daje błąd.


Możesz usunąć indeks i utworzyć nowy w jednej ALTER TABLEinstrukcji:

ALTER TABLE mytable
DROP KEY AID ,
ADD UNIQUE KEY AID (AID, BID, CID, DID);
ypercubeᵀᴹ
źródło
8

Ponieważ musisz mieć indeks w polu klucza obcego, możesz po prostu utworzyć prosty indeks w polu „AID”

CREATE INDEX aid_index ON mytable (AID);

i dopiero wtedy upuść unikalny indeks „AID”

ALTER TABLE mytable DROP INDEX AID;
Eli DM
źródło
7

Klucz obcy zawsze wymaga indeksu. Bez indeksu wymuszającego ograniczenie wymagałoby pełnego skanowania tabeli w tabeli, do której się odwołuje, dla każdego wstawionego lub zaktualizowanego klucza w tabeli odniesienia. A to miałoby niedopuszczalny wpływ na wydajność. Ma to następujące 2 konsekwencje:

  • Podczas tworzenia klucza obcego baza danych sprawdza, czy istnieje indeks. Jeśli nie, zostanie utworzony indeks. Domyślnie będzie miał taką samą nazwę jak ograniczenie.
  • Jeśli istnieje tylko jeden indeks, którego można użyć dla klucza obcego, nie można go usunąć. Jeśli naprawdę chcesz go porzucić, musisz albo usunąć ograniczenie klucza obcego, albo najpierw utworzyć dla niego inny indeks.
Stefan Mondelaers
źródło
1
masz teorię, której brakowało innym odpowiedziom.
Dennis,
1
Tak więc: jeśli masz złożony, unikalny indeks (wiele kolumn w jednym ograniczeniu), nie możesz usunąć unikalnego klucza AB, chyba że masz indeks dla A i B. Jeśli pojawi się ten błąd, inna tabela używa indeksu kolumny A lub B, i będziesz musiał je dodać, zanim będziesz mógł bezpiecznie usunąć unikat AB.
Robin De Schepper
@RobinDeSchepper Dobra uwaga. W przypadku korzystania z unikalnych indeksów złożonych kolejność pól nie jest ważna dla indeksu unikatowego, ale może być ważna w przypadku klucza obcego. Unikalny indeks na A, B może być używany przez klucz obcy na A, ale nie przez klucz obcy na B.
Stefan Mondelaers
2

Myślę, że to łatwy sposób na usunięcie indeksu.

set FOREIGN_KEY_CHECKS=1;

ALTER TABLE mytable DROP INDEX AID;

set FOREIGN_KEY_CHECKS=0;
Ram E Sh
źródło
2
Myślę, że wymieniłeś włączanie i wyłączanie kontroli. Na górze spodziewałbym się FOREIGN_KEY_CHEK=0i na końcu FOREIGN_KEY_CHEK=1.
romor
0

W moim przypadku porzuciłem klucz obcy i nadal nie mogłem upuścić indeksu. To dlatego, że była jeszcze inna tabela, która miała klucz obcy do tej tabeli w tych samych polach. Po upuszczeniu klucza obcego na drugą tabelę mogłem upuścić indeksy na tej tabeli.

jav
źródło
0

jeśli chcesz upuścić kolumnę klucza obcego (która trzyma ograniczenie) powinieneś najpierw upuścić klucz obcy, a następnie upuścić kolumnę, kiedy upuszczasz klucz obcy, nie musisz podawać całej nazwy, po prostu podaj klucz obcy Nazwa kolumny:

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

więcej szczegółów na temat:

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

OMR
źródło