MySQL Impossibile eliminare l'indice necessario in un vincolo di chiave esterna


155

Devo modificare il mio database esistente per aggiungere una colonna. Di conseguenza, voglio anche aggiornare il campo UNICO per includere quella nuova colonna. Sto cercando di rimuovere l'indice corrente ma continuo a ricevere l'erroreMySQL 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

Supponendo UNIQUE KEY AIDmytable?
Mike Purcell,

Risposte:


228

Devi rilasciare la chiave esterna. Le chiavi esterne in MySQL creano automaticamente un indice sulla tabella (c'era una domanda SO sull'argomento).

ALTER TABLE mytable DROP FOREIGN KEY mytable_ibfk_1 ; 

12
Potrebbe essere necessario aggiungerlo nuovamente dopo aver eliminato l'indice: ALTER TABLE mytableAGGIUNGI mytable_ibfk_1TASTO ESTERO VINCOLI ( AID) RIFERIMENTI mytable_a( ID) SU ELIMINA CASCATA;
Laffuste,

8
È fantastico, ma cosa posso fare se il mio FOREIGN KEYvincolo fosse anonimo?
Pehat,

@Pehat leggi la mia risposta qui sotto stackoverflow.com/a/54145440/2305119
thyzz

1
Nota: la chiave esterna potrebbe non essere così ovvia. Per trovare tutte le chiavi esterne relative a una tabella e una colonna, è possibile utilizzare questa query: dba.stackexchange.com/questions/102371/…
charlax,

84

Passo 1

Elenca chiave esterna (NOTA che è diversa dal nome dell'indice)

SHOW CREATE TABLE  <Table Name>

Il risultato ti mostrerà il nome della chiave esterna.

Formato:

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

Passo 2

Tasto Drop (chiave esterna / primaria /)

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

Passaggio 3

Rilascia l'indice.


18

Se intendi che puoi farlo:

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.

Ma allora:

ALTER TABLE mytable
DROP KEY AID ;

dà errore.


È possibile eliminare l'indice e crearne uno nuovo in ALTER TABLEun'istruzione:

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

8

Poiché devi avere un indice su un campo chiave esterna, puoi semplicemente creare un indice semplice sul campo "AID"

CREATE INDEX aid_index ON mytable (AID);

e solo allora rilasciare l'indice univoco 'AID'

ALTER TABLE mytable DROP INDEX AID;

7

Una chiave esterna richiede sempre un indice. Senza un indice che imponga il vincolo richiederebbe una scansione completa della tabella nella tabella di riferimento per ogni chiave inserita o aggiornata nella tabella di riferimento. E ciò avrebbe un impatto inaccettabile sulle prestazioni. Ciò ha le seguenti 2 conseguenze:

  • Quando si crea una chiave esterna, il database verifica l'esistenza di un indice. In caso contrario verrà creato un indice. Per impostazione predefinita, avrà lo stesso nome del vincolo.
  • Quando esiste un solo indice che può essere utilizzato per la chiave esterna, non può essere eliminato. Se davvero non vuoi rilasciarlo, devi eliminare il vincolo di chiave esterna o creare prima un altro indice.

1
hai la teoria che mancavano altre risposte.
Dennis,

1
Quindi: se si dispone di un indice univoco composto (più colonne in un vincolo univoco) non è possibile rimuovere la chiave AB univoca a meno che non si disponga di un indice per A e B. Se si verifica questo errore, un'altra tabella utilizza l'indice della colonna A o B, e dovrai aggiungerli prima di poter rimuovere in sicurezza l'AB unico.
Robin De Schepper,

@RobinDeSchepper Buona osservazione. E quando si utilizzano indici univoci composti, l'ordine dei campi non è importante per l'indice univoco, ma potrebbe essere importante per una chiave esterna. Un indice univoco su A, B può essere utilizzato da una chiave esterna su A, ma non da una chiave esterna su B.
Stefan Mondelaers,

2

Penso che questo sia un modo semplice per eliminare l'indice.

set FOREIGN_KEY_CHECKS=1;

ALTER TABLE mytable DROP INDEX AID;

set FOREIGN_KEY_CHECKS=0;

2
Penso che tu abbia scambiato abilitando e disabilitando i controlli. In cima mi sarei aspettato FOREIGN_KEY_CHEK=0e alla fine FOREIGN_KEY_CHEK=1.
Romor

0

Nel mio caso ho lasciato cadere la chiave esterna e non riuscivo ancora a far cadere l'indice. Questo perché c'era ancora un'altra tabella che aveva una chiave esterna per questa tabella sugli stessi campi. Dopo aver lasciato cadere la chiave esterna sull'altra tabella ho potuto rilasciare gli indici su questa tabella.


0

se vuoi rilasciare una colonna chiave esterna (tieni premuto un vincolo) devi prima rilasciare la chiave esterna, quindi rilasciare la colonna, quando lasci cadere la chiave esterna, non devi passare tutto il nome, semplicemente passa la chiave esterna nome della colonna:

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

maggiori dettagli su:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.