Mysql 使用复合主键作为外键

Mysql 使用复合主键作为外键,mysql,sql,Mysql,Sql,我一直认为,如果要使用引用复合主键的外键,我需要在两个表中都包含复合主键的所有列 当我无意中没有这样做并且没有收到任何错误时,我感到困惑。在下面的示例中,RoomId不是唯一的,但它本身可以用作外键 CREATE TABLE Buildings ( BuildingName VARCHAR(4) PRIMARY KEY, CampusId TINYINT, StreetAddress VARCHAR(50), City VARCHAR(30), State CHAR(2), Zip CHAR(5

我一直认为,如果要使用引用复合主键的外键,我需要在两个表中都包含复合主键的所有列

当我无意中没有这样做并且没有收到任何错误时,我感到困惑。在下面的示例中,RoomId不是唯一的,但它本身可以用作外键

CREATE TABLE Buildings (
BuildingName VARCHAR(4) PRIMARY KEY,
CampusId TINYINT,
StreetAddress VARCHAR(50),
City VARCHAR(30),
State CHAR(2),
Zip CHAR(5)
);

CREATE TABLE Rooms (
RoomId VARCHAR(5),
BuildingName VARCHAR(20) NOT NULL,
RoomType VARCHAR(15),
Capacity INT,
Notes VARCHAR(100),
CONSTRAINT FK_Buildings_Rooms FOREIGN KEY (BuildingName) REFERENCES Buildings(BuildingName),
PRIMARY KEY (RoomId, BuildingName)
);

CREATE TABLE Instructors(
EmployeeId INT AUTO_INCREMENT PRIMARY KEY,
OfficeId VARCHAR(5),
CONSTRAINT Fk_Instructors_Rooms FOREIGN KEY (OfficeId) REFERENCES Rooms(RoomId));
如果我将复合主键中的顺序切换为(BuildingName,RoomId),则外键声明将生成预期错误:
错误代码:1822。未能添加外键约束。引用的表“Rooms”中缺少约束“Fk_Instructors_Rooms”的索引

外键不需要引用唯一或主键字段。它们可以引用任何索引(主索引、唯一索引或普通索引)的第一个字段。

MySQL扩展了外键的传统定义。在大多数数据库中,它们仅限于唯一键或主键。与其他一些“扩展”一样,明确警告不要引用非唯一密钥:

但是,系统不强制要求引用的列是唯一的或声明为非空。对于诸如UPDATE或DELETE CASCADE之类的操作,没有很好地定义对非唯一键或包含空值的键的外键引用的处理建议您使用只引用唯一键(包括主键)而不引用空键的外键。

当然,不包括复合键的所有组件意味着您使用的是非唯一键


复合主键的问题很有趣。就个人而言,我认为这是使用自动递增主键的另一个原因。单列在外键声明中不太容易出错。

我从来没有这样看待它,我从来没有觉得它对我有用,所以我从来没有使用过它,但我想是这样。我的主要观点是,如果您在
(a,b,c)
上有一个索引,则可以使用
(a)
(a,b)
(a,b,c)
引用表的外键;但不是
(b)
(c)
(b,a)
,等等。。。。这就是为什么在引用索引中交换它们时出现问题的原因。