Solo per aggiungere la mia soluzione perché avevo un problema simile.
TL; DR
- Ricreare la tabella con la stessa specifica di chiave esterna ma con un nome diverso da quello precedentemente detenuto dalla tabella.
- Elimina la tabella risultante (eliminerà anche la chiave esterna orfana originale)
- Ricrea tabella con chiave esterna originale o nessuna
Dettaglio
Mi sono imbattuto nella brutta situazione in cui un'istruzione ALTER TABLE non è riuscita a causa di una chiave esterna che non è stata rilasciata in precedenza. Ciò ha portato ad alcune incongruenze nel dizionario dei dati InnoDB (probabilmente dovuto a http://bugs.mysql.com/bug.php?id=58215 ).
Domanda correlata qui: /programming/16857451/error-in-foreign-key-constraint-on-a-droped-table
mysql> ALTER TABLE `visits` CHANGE COLUMN `variation_visitor_id` `variation_visitor_id` INT(11) NOT NULL ;
Errore nella ridenominazione di './db/#sql-482c_8448f' in './db/visits' (errno: 150)
mysql> SHOW ENGINE INNODB STATUS;
Error in foreign key constraint of table db/visits:
FOREIGN KEY (`variation_visitor_id`) REFERENCES `variations_visitors` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
for correct foreign key definitippon.
Dato che non riuscivo a ripristinare la tabella # sql-482c_8448f alle visite, ho deciso di reimportarla da un backup eseguito appena prima della modifica. Tuttavia questo non è riuscito. Su indagine:
- Il vincolo era stato rimosso da INFORMATION_SCHEMA.TABLE_CONSTRAINTS e INFORMATION_SCHEMA.STATISTICS
- Ma il vincolo era ancora visibile in INFORMATION_SCHEMA.INNODB_SYS_FOREIGN;
- La tabella non esisteva, quindi non ho potuto rilasciare la chiave esterna
- Non ho potuto creare la tabella senza errori
SQL / Errori
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN WHERE ID='db/fk_visits_variations_visitors1';
+-----------------------------------+-----------+------------------------+--------+------+
| ID | FOR_NAME | REF_NAME | N_COLS | TYPE |
+-----------------------------------+-----------+------------------------+--------+------+
| db/fk_visits_variations_visitors1 | db/visits | db/variations_visitors | 1 | 48 |
+-----------------------------------+-----------+------------------------+--------+------+
Il tentativo di ricreare la tabella senza la chiave esterna ha causato un errore 150
mysql>
SET UNIQUE_CHECKS = 0;
SET FOREIGN_KEY_CHECKS = 0;
CREATE TABLE `visits` (
`id` INT(11) NOT NULL AUTO_INCREMENT ,
`variation_visitor_id` INT(11) NOT NULL ,
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SET FOREIGN_KEY_CHECKS = 1;
SET UNIQUE_CHECKS = 1;
ERROR 1005 (HY000) at line 26: Can't create table 'db.visits' (errno: 150)
mysql> SHOW ENGINE INNODB STATUS;
Error in foreign key constraint of table db/visits:
there is no index in the table which would contain
the columns as the first columns, or the data types in the
table do not match the ones in the referenced table
or one of the ON ... SET NULL columns is declared NOT NULL. Constraint:
,
CONSTRAINT "fk_visits_variations_visitors1" FOREIGN KEY ("variation_visitor_id") REFERENCES "variations_visitors" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
Il tentativo di crearlo con ha causato un errore 121
mysql>
SET UNIQUE_CHECKS = 0;
SET FOREIGN_KEY_CHECKS = 0;
CREATE TABLE `visits` (
`id` INT(11) NOT NULL AUTO_INCREMENT ,
`variation_visitor_id` INT(11) NOT NULL ,
PRIMARY KEY (`id`),
KEY `fk_visits_variations_visitors1` (`variation_visitor_id`),
CONSTRAINT `fk_visits_variations_visitors1` FOREIGN KEY (`variation_visitor_id`) REFERENCES `variations_visitors` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SET FOREIGN_KEY_CHECKS = 1;
SET UNIQUE_CHECKS = 1;
ERROR 1005 (HY000) at line 26: Can't create table 'db.visits' (errno: 121)
mysql> SHOW ENGINE INNODB STATUS;
Error in foreign key constraint creation for table `db`.`visits`.
A foreign key constraint of name `db`.`fk_visits_variations_visitors1`
already exists. (Note that internally InnoDB adds 'databasename'
in front of the user-defined constraint name.)
Note that InnoDB's FOREIGN KEY system tables store
constraint names as case-insensitive, with the
MySQL standard latin1_swedish_ci collation. If you
create tables or databases whose names differ only in
> the character case, then collisions in constraint
names can occur. Workaround: name your constraints
explicitly with unique names.
Alla fine ho usato un nuovo nome di chiave esterna. Non mi aspettavo che funzionasse, ma ha permesso la creazione della tabella.
mysql>
SET UNIQUE_CHECKS = 0;
SET FOREIGN_KEY_CHECKS = 0;
CREATE TABLE `visits` (
`id` INT(11) NOT NULL AUTO_INCREMENT ,
`variation_visitor_id` INT(11) NOT NULL ,
PRIMARY KEY (`id`),
KEY `fk_visits_variations_visitors2` (`variation_visitor_id`),
CONSTRAINT `fk_visits_variations_visitors2` FOREIGN KEY (`variation_visitor_id`) REFERENCES `variations_visitors` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SET FOREIGN_KEY_CHECKS = 1;
SET UNIQUE_CHECKS = 1;
Trascinare semplicemente la tabella dopo aver rimosso il record errato in INFORMATION_SCHEMA.INNODB_SYS_FOREIGN, consentendo un'importazione con il nome della chiave esterna originale.
my_user
ma l'errore riguardamy_db.user
...