繁体   English   中英

如何使用表中的外键另一个表中的主键

[英]How to use a Foreign key in a table a primary key in another table

我有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)
);

课程表中的 courseId 用作 CourseDetails 表中的外键。

现在我想用CourseStartDate位置和courseId从CourseDetails在另一个名为表表CourseBooking 我知道如何将 CourseStartDate Location 添加为外键。 但我很困惑如何从 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”

支持事务、行级锁定和外键

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语句,始终可以将缺失的索引添加到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 )?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM