简体   繁体   中英

Cannot ADD FOREIGN KEY using ALTER TABLE in MySQL

I want to add a foreign key to column USERNAME in table data_access_tokens , and make it reference to the parent table users column EMAIL .

I have checked (1) both USERNAME (in the child table) and EMAIL (in the parent table) are VARCHAR(128) NOT NULL; (2) EMAIL in the parent table is primary key (3) both tables use default DB engine and codepages.

Why the following SQL command to add a foreign failed:

mysql> ALTER TABLE `data_access_tokens`
    ->    ADD FOREIGN KEY (`USERNAME`)
    ->    REFERENCES `users` (`EMAIL`)
    ->    ON DELETE CASCADE;
ERROR 1215 (HY000): Cannot add foreign key constraint

This is the parent table ( users ):

mysql> show create table users;
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                          |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| users | CREATE TABLE `users` (
  `EMAIL` varchar(128) NOT NULL,
  `NAME` varchar(255) NOT NULL,
  `ENABLED` tinyint(1) NOT NULL,
  PRIMARY KEY (`EMAIL`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> desc users;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| EMAIL   | varchar(128) | NO   | PRI | NULL    |       |
| NAME    | varchar(255) | NO   |     | NULL    |       |
| ENABLED | tinyint(1)   | NO   |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

This is the child table ( data_access_tokens ):

mysql> show create table data_access_tokens;
+--------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table              | Create Table                                                                                                                                                                                                                                 |
+--------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| data_access_tokens | CREATE TABLE `data_access_tokens` (
  `TOKEN` varchar(50) NOT NULL,
  `USERNAME` varchar(128) NOT NULL,
  `EXPIRATION` datetime NOT NULL,
  `CREATION` datetime DEFAULT NULL,
  PRIMARY KEY (`TOKEN`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+--------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> desc data_access_tokens;
+------------+--------------+------+-----+---------+-------+
| Field      | Type         | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| TOKEN      | varchar(50)  | NO   | PRI | NULL    |       |
| USERNAME   | varchar(128) | NO   |     | NULL    |       |
| EXPIRATION | datetime     | NO   |     | NULL    |       |
| CREATION   | datetime     | YES  |     | NULL    |       |
+------------+--------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

In this case, the problem is that the character sets for the two tables are different. Columns in data_access_tokens are latin1 , but the column it references in users is utf8 .

You can fix this:

ALTER TABLE data_access_tokens CONVERT TO CHARACTER SET utf8;

Like many ALTER TABLE statements, this will lock the table and rewrite it. It may take some time if the table is large.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM