我的数据库包含学校,部门和课程。学校可能有也可能没有部门,并且课程与学校有关,也可能与部门无关(学校可能没有部门,或者课程可能是跨部门的)
我的表当前设置如下:
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
中的部门存在并且与学校有关。是否有更好的方法?我希望能够:
答案 0 :(得分:0)
您可以创建一个多列外键:
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)
);
但是,最好在AUTO_INCREMENT
表中使用单独的division
列,并将其用作外键。这样,您不必在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)
);
答案 1 :(得分:0)
如果始终可以创建复合外键。但是,我建议对您的设计进行以下更改:
我也建议对所有表使用自动递增的整数主键,而不要依赖手工构建的名称。
请考虑遵循上述原则的以下设计:
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'