我在 ER 中发现了一个案例,在我的一生中,我无法弄清楚如何实现参照完整性。经典的 Employee、Manager、Department 关系可以说明这个问题。
具有以下约束:
- 员工只能在一个部门工作。
- 部门可以有很多员工。
- 员工可以有一名经理在同一部门工作。
- 经理可以有多个员工在同一个部门工作。
- 没有经理的员工就是经理。
这张图说明了这个概念。
在规范化之前,我最终得到下表。
标准化后,我最终得到了这些表。
但是,仍然没有什么能阻止我在EmployeeManager
表格中意外地将在一个部门工作的经理分配给在不同部门工作的员工。
我发现的一种可能的解决方案是将 Department 放入EmployeeManager
表中并定义引用完整性约束,以便在表中{Manager, Department}
引用。{Employee, Department}
EmployeeDepartment
但是,要使其正常工作不必{Manager, Department}
是候选键吗?有没有不同的设计可以解决这个问题?
更新
好的回答我的第一个问题,不必{Manager, Department}
是候选键吗?事实证明,{Manager, Department}
表中的EmployeeManager
不一定是候选键或唯一键。它只是必须是引用表{Employee, Department}
中的外键EmployeeDepartment
。key的唯一性{Employee, Department}
没有很好的定义,并且在不同的引擎之间可能会有所不同。例如,MySQL 建议外键只引用唯一键。
此外,出于性能原因,MySQL 要求对引用的列进行索引。但是,系统不强制要求引用的列必须是 UNIQUE 或声明为 NOT NULL。对于 UPDATE 或 DELETE CASCADE 等操作,对非唯一键或包含 NULL 值的键的外键引用的处理没有明确定义。建议您使用仅引用 UNIQUE(包括 PRIMARY)和 NOT NULL 键的外键。
就我而言,它会起作用,因为员工只能在一个部门工作,但是如果限制机会允许员工在多个部门工作,它就不会起作用,因为{Employee, Department}
将不再是唯一的。
它应该适用于所有情况,包括是否允许员工在多个部门工作的约束机会。
有没有不同的设计可以解决这个问题?我还考虑过用作为主键的表替换并返回到EmployeeDepartment
带有列的前一个表。因此,现在要找出员工工作的部门,您需要加入表。ManagerDepartment
{Manager}
EmployeeManager
(Employee, Manager)
EmployeeManager
ManagerDepartment
您是否发现此设计有任何不良做法或异常情况?