O MySQL não pode eliminar o índice necessário em uma restrição de chave estrangeira

155

Eu preciso ALTERAR meu banco de dados existente para adicionar uma coluna. Consequentemente, também quero atualizar o campo UNIQUE para abranger essa nova coluna. Estou tentando remover o índice atual, mas continuo recebendo o erroMySQL 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
fonte
Assumindo UNIQUE KEY AIDminha tabela?
Mike Purcell

Respostas:

228

Você precisa soltar a chave estrangeira. Chaves estrangeiras no MySQL criam automaticamente um índice na tabela (havia uma pergunta SO no tópico).

ALTER TABLE mytable DROP FOREIGN KEY mytable_ibfk_1 ; 
Brian Fisher
fonte
12
Você pode querer adicioná-lo novamente depois de soltar o índice: ALTER TABLE mytableADD CONSTRAINT mytable_ibfk_1FOREIGN KEY ( AID) REFERÊNCIAS mytable_a( ID) ON DELETE CASCADE;
Laffuste
8
Isso é ótimo, mas o que posso fazer se minha FOREIGN KEYrestrição for anônima?
Pehat 08/07/16
@Pehat, verifique minha resposta abaixo stackoverflow.com/a/54145440/2305119
thyzz
1
Nota: a chave estrangeira pode não ser tão óbvia. Para encontrar todas as chaves estrangeiras relacionadas com uma mesa e coluna, você pode usar essa consulta: dba.stackexchange.com/questions/102371/...
charlax
84

Passo 1

Listar chave estrangeira (NOTE que é diferente do nome do índice)

SHOW CREATE TABLE  <Table Name>

O resultado mostrará o nome da chave estrangeira.

Formato:

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

Passo 2

Tecla Drop (estrangeira / principal / chave)

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

etapa 3

Solte o índice.

Abhishek Goel
fonte
18

Se você quer dizer que pode fazer isso:

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.

Mas então:

ALTER TABLE mytable
DROP KEY AID ;

dá erro.


Você pode soltar o índice e criar um novo em uma ALTER TABLEinstrução:

ALTER TABLE mytable
DROP KEY AID ,
ADD UNIQUE KEY AID (AID, BID, CID, DID);
ypercubeᵀᴹ
fonte
8

Como você precisa ter um índice em um campo de chave estrangeira, basta criar um índice simples no campo 'AID'

CREATE INDEX aid_index ON mytable (AID);

e só então solte o índice exclusivo 'AID'

ALTER TABLE mytable DROP INDEX AID;
Eli DM
fonte
7

Uma chave estrangeira sempre exige um índice. Sem um índice que imponha a restrição, seria necessária uma verificação completa da tabela na tabela referenciada para cada chave inserida ou atualizada na tabela de referência. E isso teria um impacto inaceitável no desempenho. Isso tem as seguintes 2 consequências:

  • Ao criar uma chave estrangeira, o banco de dados verifica se existe um índice. Caso contrário, um índice será criado. Por padrão, ele terá o mesmo nome que a restrição.
  • Quando existe apenas um índice que pode ser usado para a chave estrangeira, ela não pode ser descartada. Se você realmente não deseja eliminá-lo, é necessário eliminar a restrição de chave estrangeira ou criar outro índice primeiro.
Stefan Mondelaers
fonte
1
você tem a teoria de que faltam outras respostas.
Dennis
1
Portanto: se você tiver um índice exclusivo composto (várias colunas em uma restrição exclusiva), não poderá remover a chave AB exclusiva, a menos que tenha um índice para A e B. Se você receber esse erro, outra tabela estará usando o índice da coluna A ou B e você precisará adicioná-los antes de poder remover com segurança o AB exclusivo.
Robin De Schepper
@RobinDeSchepper Good observação. E ao usar índices exclusivos compostos, a ordem dos campos não é importante para o índice exclusivo, mas pode ser importante para uma chave estrangeira. Um índice exclusivo em A, B pode ser usado por uma chave estrangeira em A, mas não por uma chave estrangeira em B.
Stefan Mondelaers
2

Eu acho que essa é uma maneira fácil de eliminar o índice.

set FOREIGN_KEY_CHECKS=1;

ALTER TABLE mytable DROP INDEX AID;

set FOREIGN_KEY_CHECKS=0;
Ram E Sh
fonte
2
Eu acho que você trocou ativando e desativando os cheques. No topo eu esperava FOREIGN_KEY_CHEK=0e no final FOREIGN_KEY_CHEK=1.
Romor #
0

No meu caso, larguei a chave estrangeira e ainda não consegui largar o índice. Isso ocorreu porque havia mais uma tabela que tinha uma chave estrangeira para essa tabela nos mesmos campos. Depois de soltar a chave estrangeira na outra tabela, eu poderia soltar os índices nessa tabela.

jav
fonte
0

se você deseja soltar uma coluna de chave estrangeira (o que mantém uma restrição), você deve soltar a chave estrangeira primeiro e depois soltar a coluna; quando você solta a chave estrangeira, não precisa passar todo o nome, basta passar a chave estrangeira nome da coluna:

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

mais detalhes sobre:

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

OMR
fonte