【问题标题】: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
  • 需要两次查询才能得到学校和部门

有没有更好的方法来做到这一点?我希望能够:

  • 查询所有“哈佛”课程
  • 查询所有“哈佛工程”课程
  • 查询所有“哈佛工程与哈佛通用”课程

【问题讨论】:

    标签: mysql sql database orm


    【解决方案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'
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-14
        • 1970-01-01
        • 2012-05-28
        • 2012-12-29
        • 2010-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多