我有3张桌子。课程,课程详细信息,课程预订。
课程
CREATE TABLE Courses (
courseId int NOT NULL,
courseName varchar(255),
level varchar(255),
description varchar(255),
PRIMARY KEY (courseId)
);
课程详细信息
CREATE TABLE CourseDetails (
CourseStartDate int NOT NULL,
Location varchar(255) NOT NULL,
MaxNoPlaces int,
Length int,
Instructor varchar(255),
TotalPlacesBooked int,
NoPlacesCancelled int,
AdultPrice int,
ChildPrice int,
courseId int,
CONSTRAINT PK_CourseDetails PRIMARY KEY (CourseStartDate,Location,courseId),
FOREIGN KEY (courseId) REFERENCES Courses(courseId)
);
来自Course表的courseId用作CourseDetails表中的外键。
现在,我想在另一个名为CourseStartDate
的表中使用CourseDetails
表中的CourseBooking
Location&courseId。我知道如何将CourseStartDate位置添加为外键。但是我很困惑如何从CourseDetails表中将courseId添加为新CourseBookings
表中的外键。
我尝试了以下
CREATE TABLE CourseBookings (
CourseStartDate int NOT NULL,
Location varchar(255) NOT NULL,
GuestNo int,
courseId int,
CONSTRAINT PK_CourseDetails PRIMARY KEY (CourseStartDate,Location,GuestNo,courseId),
FOREIGN KEY (courseId) REFERENCES CourseDetails.courseId(courseId),
FOREIGN KEY (CourseStartDate) REFERENCES CourseDetails(CourseStartDate),
FOREIGN KEY (Location) REFERENCES CourseDetails(Location),
FOREIGN KEY (GuestNo) REFERENCES Guest(GuestNo)
);
但是有一个错误提示
无法创建表'b8040777_db1.CourseBookings'
支持事务,行级锁定和外键
答案 0 :(得分:2)
表CourseBookings
的声明存在几个问题。
问题1
此:
FOREIGN KEY (courseId) REFERENCES CourseDetails.courseId(courseId),
应写为:
FOREIGN KEY (courseId) REFERENCES CourseDetails(courseId),
问题2
表CourseDetails
的外键引用的CourseBookings
列之一没有索引。
MySQL要求在外键和引用键上建立索引,以便外键检查可以快速进行,而无需进行表扫描。在引用表中,必须有一个索引,其中外键列以相同的顺序列为第一列。如果该索引不存在,则会在引用表上自动创建。
在表CourseDetails
中:
courseId
具有自动创建的索引,因为它引用了Courses(courseId)
CourseStartDate
没有索引,但是它是由主键约束声明自动生成的索引中的第一列Location
没有索引,它只是主键索引中的第二列->无法创建引用它的外键,尝试时会出现错误解决方案1
始终可以通过将缺失的索引添加到表CREATE TABLE CourseDetails
中来将缺失的索引添加到表中:
INDEX idx_Location (Location)
解决方案2
在您的用例中,我怀疑您实际需要的是一个多列外键(仅在InnoDB中受支持),该外键引用CourseDetails
的主键(这些列上已经存在一个索引)。这样,您就可以将CourseBookings
的每个记录与CourseDetails
中的唯一父记录相关联。
DDL建议:
CREATE TABLE CourseBookings (
CourseStartDate int NOT NULL,
Location varchar(255) NOT NULL,
GuestNo int,
courseId int,
CONSTRAINT PK_CourseDetails PRIMARY KEY (CourseStartDate,Location,courseId,GuestNo),
FOREIGN KEY (CourseStartDate,Location,courseId)
REFERENCES CourseDetails(CourseStartDate,Location,courseId),
FOREIGN KEY (GuestNo) REFERENCES Guest(GuestNo)
);
解决方案3
如果解决方案2适合您的用例,则意味着可以通过在表CourseDetails
上创建一个自动递增的整数主键来优化您的模式。可以将现有的主键转换为UNIQUE
约束。然后,在表CourseBookings
中,您可以仅将外键存储到该列。
这将为您提供一种简单有效的方法,将一个表与另一个表相关联,同时避免在表之间重复信息(实际上,您在CourseBookins
中仅留下3列)。
在关系数据库设计中,通常最好在大多数表上创建这样的主键。您也可以考虑将一个表添加到其他表中。
示例:
CREATE TABLE CourseDetails (
id int PRIMARY KEY AUTO_INCREMENT,
CourseStartDate int NOT NULL,
...
CONSTRAINT PK_CourseDetails UNIQUE (CourseStartDate,Location,courseId),
FOREIGN KEY (courseId) REFERENCES Courses(courseId)
);
CREATE TABLE CourseBookings (
id int PRIMARY KEY AUTO_INCREMENT,
courseDetailId INT NOT NULL,
GuestNo int,
CONSTRAINT PK_CourseBookings UNIQUE (courseDetailId,GuestNo),
FOREIGN KEY (courseDetailId) REFERENCES CourseDetails(id),
FOREIGN KEY (GuestNo) REFERENCES Guest(GuestNo)
);
PS,以防万一:
FOREIGN KEY (GuestNo) REFERENCES Guest(GuestNo)
表Guest
是否存在于您的模式中(您没有显示CREATE TABLE
)?