数据库设计 - 多个外键
Posted
技术标签:
【中文标题】数据库设计 - 多个外键【英文标题】:Database design - multiple foreign keys 【发布时间】:2019-10-09 22:30:58 【问题描述】:我的数据库包含学校、部门和课程。学校可以有分部,也可以没有,课程跟学校有关系,也可以不和分部有关(学校可以没有分部,也可以跨分部)
我的桌子目前设置如下:
school
:
ID | name
--------------------
harvard | Harvard University
mit | MIT
ucla | UCLA
division
(id+school=unique)
ID | school (FK) | name
------------------------------------------
eng | harvard | School of Engineering
arc | harvard | School of Architecture
eng | UCLA | UCLA Engineering
course
:
ID | school (FK) | division | name
-------------------------------------------------
1 | harvard | eng | Intro to Engineering
2 | harvard | arc | Intro to Architecture
3 | harvard | | Statistics
4 | mit | | Math
我对此的担忧:
没有验证以确保course
中的部门存在并且与学校相关。
除法实际上不是 fk
需要两次查询才能得到学校和部门
有没有更好的方法来做到这一点?我希望能够:
查询所有“哈佛”课程 查询所有“哈佛工程”课程 查询所有“哈佛工程与哈佛通用”课程【问题讨论】:
【参考方案1】:您可以创建一个多列外键:
CREATE TABLE course (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
school VARCHAR(50),
division VARCHAR(50),
name VARCHAR(50),
FOREIGN KEY (school, division) REFERENCES division(school, id)
);
但是,在division
表中使用单独的AUTO_INCREMENT
列并将其用作外键可能会更好。这样您就不必在 course
表中复制两列。
CREATE TABLE division (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
division_code VARCHAR(50),
school VARCHAR(50),
name VARCHAR(50),
UNIQUE KEY (division_code, school),
FOREIGN KEY (school) REFERENCES school (id)
);
CREATE TABLE course (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
division_id INT(11),
name VARCHAR(50),
FOREIGN KEY (division_id) REFERENCES division(id)
);
【讨论】:
【参考方案2】:如果总是可以创建复合外键。但是,我建议对您的设计进行以下更改:
为每所学校创建一个默认部门,称为“General” 允许同一课程存在于不同学校的可能性(在现实生活中,这可能会发生)。我还建议对所有表使用自动递增的整数主键,而不是依赖手动构建的名称。
考虑以下设计,它遵循上述原则:
school
id primary key
name
division
id primary key
school_id foreign key to school(id)
name
course
id primary key
name
course_division
id primary key
course_id foreign key to course(id)
division_id foreign key to course(id)
现在这里是使用此架构的查询。
查询所有“哈佛”课程
SELECT c.*
FROM course c
INNER JOIN division d ON d.id = cd.division_id
INNER JOIN school s ON s.id = d.school_id AND s.name = 'Harvard University'
查询所有“哈佛工程”课程
SELECT c.*
FROM course c
INNER JOIN course_division cd ON cd.id = c.course_id
INNER JOIN division d ON d.id = cd.division_id AND d.name = 'School of Engineering'
INNER JOIN school s ON s.id = d.school_id AND s.name = 'Harvard University'
查询所有“哈佛工程与哈佛通识”课程
SELECT c.*
FROM course c
INNER JOIN course_division cd ON cd.id = c.course_id
INNER JOIN division d ON d.id = cd.division_id AND d.name IN ('School of Engineering', 'General')
INNER JOIN school s ON s.id = d.school_id AND s.name = 'Harvard University'
【讨论】:
以上是关于数据库设计 - 多个外键的主要内容,如果未能解决你的问题,请参考以下文章