MySQL - Error: 150 "Foreign key constraint is incorrectly formed")

MySQL - Error: 150 "Foreign key constraint is incorrectly formed")

遇到一个奇怪的问题,在浏览了数十个论坛帖子和我的本地 SQL 书籍后仍无法解决。

我有两张表,想给其中一张添加外键。外键和主键共享相同的数据类型和字符集,但我根本无法添加外键。

addon_account

name type comments
id int(11) Primary Key
name varchar(60) Primary Key
label varchar(255)
shared int(11)

addon_account_data

name type comments
id int(11) Primary Key
account_name varchar(60) Primary Key
money double
owner varchar()

查询我运行:

ALTER TABLE `addon_account_data` ADD FOREIGN KEY (`account_name`) REFERENCES `addon_account`(`name`) ON DELETE RESTRICT ON UPDATE RESTRICT;

无法正常工作。一直抛出同一个问题。

我不完全是 MySQL 人,但是:

我认为问题在于您仅引用了主键的一部分: 您的 table addon_account 有一个复合键 PK(id, name)。

因此,为了让你们的关系发挥作用,您还需要添加 'account_id' 作为外键的一部分:

ALTER TABLE addon_account_data ADD FOREIGN KEY (account_id, account_name) REFERENCES addon_account(id, name)

This thread 处理类似的事情。

希望对您有所帮助。

已编辑

我已经在我的本地机器上安装了一个 MySQL 服务器实例... (MySQL 8).

我有 运行 下面的脚本,它有效(给出关于整数显示是不推荐使用的功能的警告,所以我建议忽略它):

CREATE TABLE addon_account(
id INT(11) NOT NULL,
`name` VARCHAR(60) NOT NULL,
label VARCHAR(255),
shared INT(11),
CONSTRAINT pk_addon_account PRIMARY KEY(id, `name`));


CREATE TABLE addon_account_data (
id INT(11) NOT NULL,
account_name VARCHAR(60) NOT NULL,
account_id INT(11),
money DOUBLE,
`owner` VARCHAR(255),
CONSTRAINT pk_addon_account_data PRIMARY KEY(id, account_name),
CONSTRAINT fk_addon_account_account_data FOREIGN KEY(account_id, account_name)
    REFERENCES addon_account(id, `name`));

你能试试看这对你有用吗?

我对MySQL不太熟悉。

您正在 addon_account_data(account_name) 上创建引用 addon_account(name) 的外键。你有一个复合主引用 table : addon_account(id, name).

这在 MySQL 中是不允许的,如 documentation 中所述:

MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order.

可能的解决方案:

  • 在引用 table 中添加一个附加列:addon_account_data(account_id, account_name) 并为 addon_account

    中的相应列创建一个复合主键
  • addon_account(name) 上创建索引(可能是最简单的解决方案)

  • 更改所引用 table 的主键中列的顺序,例如:addon_account(name, id)(您可能需要首先考虑这可能对术语产生的影响性能)

确保 2 个表具有相同的排序规则 像 整理='utf8_general_ci'