MySQL 中的外键引用,使用类似的引用列,不起作用
Foreign key reference in MySQL, using similar referenced column, not woking
这里有两个代码
CREATE TABLE tab1 (
col1 int,
col2 int,
PRIMARY KEY(col1, col2)
);
CREATE TABLE tab2 (
col1 int,
FOREIGN KEY (col1) REFERENCES tab1(col1)
);
CREATE TABLE tab1 (
col1 int,
col2 int,
PRIMARY KEY(col1, col2)
);
CREATE TABLE tab2 (
col1 int,
FOREIGN KEY (col1) REFERENCES tab1(col2) <- difference point (col2 used instead of col1)
);
第一个代码有效,但第二个无效。错误如下:
SQL Error [1822] [HY000]: Failed to add the foreign key constraint. Missing index for constraint 'tab2_ibfk_1' in the referenced table 'tab1'.
但为什么会这样呢?
顺便说一句,我在执行第二个代码之前清除了数据库。所以这不是因为存在一些重复的表格。
而且 this 回答说,外键不能引用可能包含重复值的列。但在我的例子中,如果 (1, 1) 和 (1, 2) 插入 tab1
,那么当 col1
引用自 tab2
时,col1
确实包含重复项条目。
我正在使用 Ubuntu 20.04.
标准SQL 要求您定义外键以引用父table 的整个主键或唯一键。如果该主键有两列,那么您的外键也必须有两列。所以你不应该尝试做你展示的任何一种情况。
InnoDB 允许偏离标准规则:它允许外键引用父 table 中主键列的子集,只要该子集是最左边的列。父 table 中的键甚至不需要是主键或唯一键。它可以只是一个普通的二级索引。
但这会产生一些奇怪的边缘情况,从而引起麻烦。如果您可以在子 table 中创建一行引用父 table 中的多行,那么如果父 table 中的其中一行被删除会怎样?这是否违反了外键?应该允许吗?如果删除父行 table 中的一行是该子行的 only 父行,这是否只是一个错误?哪种行为是正确的?
我强烈建议您不要走那条路。始终确保定义仅引用父项 table 中的主键或唯一键的外键,并始终使用与其引用的键相同的列集定义外键。这样一来,子行就可以保证恰好引用父行中的一行 table,所有奇怪的问题都会消失。
这里有两个代码
CREATE TABLE tab1 (
col1 int,
col2 int,
PRIMARY KEY(col1, col2)
);
CREATE TABLE tab2 (
col1 int,
FOREIGN KEY (col1) REFERENCES tab1(col1)
);
CREATE TABLE tab1 (
col1 int,
col2 int,
PRIMARY KEY(col1, col2)
);
CREATE TABLE tab2 (
col1 int,
FOREIGN KEY (col1) REFERENCES tab1(col2) <- difference point (col2 used instead of col1)
);
第一个代码有效,但第二个无效。错误如下:
SQL Error [1822] [HY000]: Failed to add the foreign key constraint. Missing index for constraint 'tab2_ibfk_1' in the referenced table 'tab1'.
但为什么会这样呢?
顺便说一句,我在执行第二个代码之前清除了数据库。所以这不是因为存在一些重复的表格。
而且 this 回答说,外键不能引用可能包含重复值的列。但在我的例子中,如果 (1, 1) 和 (1, 2) 插入 tab1
,那么当 col1
引用自 tab2
时,col1
确实包含重复项条目。
我正在使用 Ubuntu 20.04.
标准SQL 要求您定义外键以引用父table 的整个主键或唯一键。如果该主键有两列,那么您的外键也必须有两列。所以你不应该尝试做你展示的任何一种情况。
InnoDB 允许偏离标准规则:它允许外键引用父 table 中主键列的子集,只要该子集是最左边的列。父 table 中的键甚至不需要是主键或唯一键。它可以只是一个普通的二级索引。
但这会产生一些奇怪的边缘情况,从而引起麻烦。如果您可以在子 table 中创建一行引用父 table 中的多行,那么如果父 table 中的其中一行被删除会怎样?这是否违反了外键?应该允许吗?如果删除父行 table 中的一行是该子行的 only 父行,这是否只是一个错误?哪种行为是正确的?
我强烈建议您不要走那条路。始终确保定义仅引用父项 table 中的主键或唯一键的外键,并始终使用与其引用的键相同的列集定义外键。这样一来,子行就可以保证恰好引用父行中的一行 table,所有奇怪的问题都会消失。