Mysql 数据库设计-多个外键
我的数据库包含学校、部门和课程。学校可以有分部,也可以没有分部,课程与学校相关,也可以有分部,也可以没有分部(学校可以没有分部,或者课程可以跨分部) 我的表格当前设置如下:Mysql 数据库设计-多个外键,mysql,sql,database,orm,Mysql,Sql,Database,Orm,我的数据库包含学校、部门和课程。学校可以有分部,也可以没有分部,课程与学校相关,也可以有分部,也可以没有分部(学校可以没有分部,或者课程可以跨分部) 我的表格当前设置如下: 学校: ID | name -------------------- harvard | Harvard University mit | MIT ucla | UCLA 部门(id+学校=唯一) 课程: ID | school (FK) | division | name --------
学校
:
ID | name
--------------------
harvard | Harvard University
mit | MIT
ucla | UCLA
部门
(id+学校=唯一)
课程
:
ID | school (FK) | division | name
-------------------------------------------------
1 | harvard | eng | Intro to Engineering
2 | harvard | arc | Intro to Architecture
3 | harvard | | Statistics
4 | mit | | Math
我对此表示关注:
- 没有验证来确保
中的分区存在并且与学校相关课程
- 分裂实际上不是一个fk
- 需要两个查询才能得到学校和部门
- 查询所有“哈佛”课程
- 查询所有“哈佛工程”课程
- 查询所有“哈佛工程和哈佛通识”课程
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)
);
但是,最好在分区
表中使用单独的自动增量
列,并将其用作外键。这样,您就不必在课程
表中重复两列
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)
);
如果总是可以创建复合外键。但是,我建议对您的设计进行以下更改:
- 为每个学校创建一个名为“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)
下面是使用此模式的查询 查询所有“哈佛”课程 查询所有“哈佛工程”课程 查询所有“哈佛工程和哈佛通识”课程
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'