这是一个糟糕的数据库设计吗?

时间:2015-10-06 20:11:38

标签: sql database-design

我有两个表,TeachersDepartments

Teachers在某个部门工作,因此教师表中有一个department_id个外键。

每个部门都有一名教师担任主席。因此,Department有一个 外键chairman引用Teachers表。

但是,教师表可以包含来自许多部门的教师。但是主席必须是同一部门的老师。所以,它似乎很陌生 key应该引用教师子集而不是整个表。

我有两个问题。

  1. 这是一个糟糕的设计,因为无效的老师可以作为负责人进入Department表吗?

  2. 如果没有,我该如何在数据库中强制执行此操作?

4 个答案:

答案 0 :(得分:2)

这不是一个糟糕的数据库设计,因为从关系的角度来看,关系很好。

您的要求是一个应用程序问题,因此可以在应用程序层处理它,这意味着,在使用此数据库的应用程序中付出痛苦,以确保主席始终属于他们所在的部门。主持。

但是,关系数据库是否只是为了强制执行有关实体的自然关系的规则,或者它们是否也应该执行业务规则,这个问题是一个哲学问题。您也可以尝试执行业务规则,但是您应该知道并非所有业务规则都可以由数据库强制执行,也不可能由数据库强制执行。

如果你坚持走那条路,那么rlb的评论指向一个不错的解决方案。 (在该帖子中查找另一条评论,该评论指向另一篇文章,其中显示了如何从触发器中生成错误。)

答案 1 :(得分:1)

你应该考虑另一种设计方式:将老师标记为主席(主席为'Y',其他为空),并在(department_id,主席)上设置唯一密钥

oracle中的

create unique index chairman_uq_idx on teacher(department_id, nvl(chairman, teacher_id))

在其他数据库中:create unique index chairman_uq_idx on teacher(department_id, chairman) where chairman is not null

有两个简单的原因:

  1. 表格之间的循环引用总是潜在的麻烦来源
  2. ORM子类化 - 主席是教师的专业化

答案 2 :(得分:1)

你的设计做了很多假设。

  1. 老师只能在一个部门。
  2. 每个部门只能有一位主席。
  3. 董事长是您唯一想要存储的职位。
  4. 你不想再了解董事长。
  5. 只有教师可以担任主席。
  6. 如果这些假设在房地产中成立,您可以通过利用教师只能在一个部门中来解决您的难题。移动"主席"标志到老师表。这保证了主席是该部门的成员。

    然而,我认为这些假设在与现实的碰撞中不会幸存。如果他们不这样做,则会涉及您的架构和查询的重大重组。我将重构架构以存储更通用的员工并将教师转换为部门角色。员工和部门处于多对多的关系中。这种关系可用于存储关系类型以及任何进一步的信息。

    CREATE TABLE staff (
        id    INTEGER PRIMARY KEY,
        name  TEXT NOT NULL
    );
    
    CREATE TABLE departments (
        id    INTEGER PRIMARY KEY,
        name  TEXT NOT NULL
    );
    
    CREATE TABLE department_roles (
        staff_id      INTEGER REFERENCES staff(id),
        department_id INTEGER REFERENCES departments(id),
        role          ENUM('chairman', 'teacher')
    );
    

    这种布局保证了主席在自己的部门。 department_roles上的约束可以强制执行业务逻辑,例如每个部门有一个主席,或者只有教师可以担任主席,以后可以删除或更改它们而不会影响查询。它允许在将来添加角色。它允许向这些角色添加更多信息。它允许非教师担任部门角色。

答案 3 :(得分:1)

根据其他帖子,有很多方法可以解决这个问题,而且一旦你100%确定实际解决的问题(见。@ Schwern的帖子)。以下可能有点尴尬,但我在类似情况下使用这种结构效果很好。

教师表看起来像:

TEACHER
TeacherId
DepartmentId

有约束:

  • {TeacherId}上的主键
  • 对(TeacherId,DepartmentId}
  • 的唯一约束

以下外键需要唯一约束。

部门表格如下:

DEPARTMENT
DepartmentId
ChairmanId

有约束:

  • {DepartmentId}
  • 上的主键
  • 对(uniqueId,DepartmentId)的外键约束进入表TEACHER,针对唯一约束

您必须至少使用一个ChairmanId或TEACHER.DepartmentId为NULL,否则您将永远无法加载数据。