我一直认为,如果要使用引用复合主键的外键,则需要在两个表中都包括复合主键的所有列。
当我无意间没有这样做并且没有收到任何错误时,我感到困惑。在下面的示例中,RoomId ISN不是唯一的,但允许其单独用作外键。
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),则外键声明会产生预期的错误:
Error Code: 1822. Failed to add the foreign key constraint. Missing index for constraint 'Fk_Instructors_Rooms' in the referenced table 'rooms'
答案 0 :(得分:1)
MySQL扩展了外键的传统定义。在大多数数据库中,它们仅限于唯一键或主键。与其他“扩展名”一样,documentation明确警告不要引用非唯一密钥:
但是,系统不强制要求引用的列为UNIQUE或声明为NOT NULL。对于诸如UPDATE或DELETE CASCADE之类的操作,未很好地定义对非唯一键或包含NULL值的键的外键引用的处理。 建议您使用仅引用UNIQUE(包括PRIMARY)和NOT NULL键的外键。
当然,不包括组合键的所有组件意味着您使用的是非唯一键。
您的复合主键问题很有趣。就个人而言,我会把它归为使用自动递增主键的另一个原因。单列在外键声明中不太容易出错。
答案 1 :(得分:0)
外键不需要引用唯一或主键字段。他们可以引用任何索引(主索引,唯一索引或纯索引)的第一个字段。