问题
I am trying to run a foreign key add query as below, with foreign key checks set to 0. Both the columns in the two tables are exactly the same. Also, both are primary keys. None of the solutions here helped in solving this problem. I'm on localhost.
mysql> alter table deliveryaddress
-> add foreign key(oid) references productorder(oid)
-> on delete cascade on update restrict;
ERROR 1822 (HY000): Failed to add the foreign key constaint. Missing index for c
onstraint '' in the referenced table 'productorder'
mysql> desc productorder;
+----------------+--------------+------+-----+-------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+-------------------+-------+
| primenumber | varchar(15) | NO | PRI | NULL | |
| oid | varchar(10) | NO | PRI | NULL | |
| orderdatetime | timestamp | NO | | CURRENT_TIMESTAMP | |
| addressname | varchar(30) | NO | | NULL | |
| deliverycharge | decimal(8,2) | YES | | 20.00 | |
+----------------+--------------+------+-----+-------------------+-------+
5 rows in set (0.02 sec)
mysql> desc deliveryaddress;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| oid | varchar(10) | NO | PRI | NULL | |
| pincode | varchar(8) | NO | | NULL | |
| area | varchar(60) | NO | | NULL | |
| city | varchar(60) | NO | | NULL | |
| state | varchar(60) | NO | | NULL | |
| landmark | varchar(60) | YES | | NULL | |
| phone | varchar(15) | NO | | NULL | |
| locality | varchar(60) | NO | | NULL | |
+----------+-------------+------+-----+---------+-------+
8 rows in set (0.00 sec)
mysql>
回答1:
It looks like productorder.oid
is part of a multi-column primary key, and it's not the leftmost column in the primary key. (In the future, please include the result of SHOW CREATE TABLE <tablename>
because it is more clear than DESCRIBE about things like multi-column keys.)
When you declare a foreign key, you must reference the leftmost column of the primary key.
When you reference a multi-column primary key, the foreign key must have the same number of columns in the same order.
Wrong (not enough columns, and referencing second column of primary key):
CREATE TABLE parent (x INT, y INT, PRIMARY KEY (x, y));
CREATE TABLE child (y INT, FOREIGN KEY (y) REFERENCES parent(y));
Wrong (individual foreign keys each referencing part of the composite primary key):
CREATE TABLE parent (x INT, y INT, PRIMARY KEY (x, y));
CREATE TABLE child (x INT, y INT,
FOREIGN KEY (x) REFERENCES parent(x),
FOREIGN KEY (y) REFERENCES parent(y)
);
Right (same columns):
CREATE TABLE parent (x INT, y INT, PRIMARY KEY (x, y));
CREATE TABLE child (x INT, y INT, FOREIGN KEY (x, y) REFERENCES parent(x, y));
Re your comment:
I'm now thinking that your real problem is that you have the relationship reversed. You are trying to declare a foreign key in deliveryaddress
referencing productorder
, but I would expect the reference to go the other direction.
ALTER TABLE productorder ADD FOREIGN KEY (oid) REFERENCES deliveryaddress (oid);
Then you have no error, because the primary key of deliveryaddress
is just one column.
I believe this relationship makes more sense in a typical e-commerce application. There are many orders that might reference the same address. The opposite relationship is probably not what you want, because it makes no sense for many addresses to reference a single product order.
回答2:
You have a composite primary key -- it consists of two keys together, (oid, primenumber)
.
You should use both keys to define the foreign key definition.
Alternatively, define an auto-incremented primary key and use that.
回答3:
I recreated the table with index on oid
that was generating missing index problem.
mysql> create table productorder
-> (
-> primenumber varchar(15) not null,
-> oid varchar(10) not null,
-> orderdatetime timestamp not null default current_timestamp,
-> addressname varchar(30) not null,
-> deliverycharge decimal(8,2) not null default 20,
-> primary key(oid, primenumber), index(oid), index(primenumber),
-> foreign key(primenumber) references user(primenumber) on delete cascade
n update restrict
-> );
Query OK, 0 rows affected (1.52 sec)
mysql> alter table deliveryaddress
-> add foreign key(oid) references productorder(oid)
-> on delete cascade on update restrict;
Query OK, 0 rows affected (0.19 sec)
Records: 0 Duplicates: 0 Warnings: 0
来源:https://stackoverflow.com/questions/59554952/unable-to-add-foreign-key-in-mysql-5-7-missing-constraint-in-the-referenced-tab