我有两个表,Teachers
和Departments
。
Teachers
在某个部门工作,因此教师表中有一个department_id
个外键。
每个部门都有一名教师担任主席。因此,Department
有一个
外键chairman
引用Teachers
表。
但是,教师表可以包含来自许多部门的教师。但是主席必须是同一部门的老师。所以,它似乎很陌生 key应该引用教师子集而不是整个表。
我有两个问题。
这是一个糟糕的设计,因为无效的老师可以作为负责人进入Department
表吗?
如果没有,我该如何在数据库中强制执行此操作?
答案 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
有两个简单的原因:
答案 2 :(得分:1)
你的设计做了很多假设。
如果这些假设在房地产中成立,您可以通过利用教师只能在一个部门中来解决您的难题。移动"主席"标志到老师表。这保证了主席是该部门的成员。
然而,我认为这些假设在与现实的碰撞中不会幸存。如果他们不这样做,则会涉及您的架构和查询的重大重组。我将重构架构以存储更通用的员工并将教师转换为部门角色。员工和部门处于多对多的关系中。这种关系可用于存储关系类型以及任何进一步的信息。
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
有约束:
以下外键需要唯一约束。
部门表格如下:
DEPARTMENT
DepartmentId
ChairmanId
有约束:
您必须至少使用一个ChairmanId或TEACHER.DepartmentId为NULL,否则您将永远无法加载数据。