用于递归关系的数据库设计
考虑这种情况下,我试图为公司建立数据库模型:
Employees
, Managers
, Departments
。 Employee
只有1工作Department
,同时一个Department
可能有许多Employees
在正常工作。 Manager
可能只管理一个Department
,同样一个Department
可能只有一个Manager
。 Manager
监督许多Employees
,但Employee
只能由一位Manager
监督。 现在我有两种方法来模拟这个:
第一解
考虑到我将保留经理人特有的数据(例如奖金和状态),我会考虑Manager
实体从Employee
实体继承。
由于Department
和Employee
之间的关系是1:N
因此我将Department Id
作为Works
关系的Employee
表中的外键。
由于Department
和Manager
之间的关系是1:1
因此我将Department Id
作为Manages
关系的Manager
表中的外键。
问题:如何表示Manager
和Employee
之间的递归关系?
第二种方案
我会考虑Manager
实体不需要,因为其他Employees
也可能有Bonus
和Status
。 (其实我加了这两个属性只是为了看看如何在两种情况下建模)
Department
和Employee
之间的关系是1:N
因此我将Department Id
作为Works
关系的Employee
表中的外键。 Employee
和Manager
之间的关系是1:N
我将Employee Id
作为外部关键字放入Supervises
关系的Employee
表中,并将其称为Manager Id
。 问题:如何表示Manager
与Department
之间的关系?
问题:
我可能会用类似的东西:
该模型具有以下特点:
注意:如果您的DBMS不支持延迟约束,您需要使DEPARTMENT.MANAGER_ID为NULL,以打破循环,否则会妨碍您插入新数据。
如果部门需要匹配,那么您要么采用特定于DBMS的技术(例如触发器或“特殊”约束),要么将DEPARTMENT_ID“传播”到员工的PK中。 这种传播最终实现了匹配:
由于EMPLOYEE_ID必须是全局唯一的,因此它不能与DEPARTMENT_ID一起保留在组合键中。 因此,我们使用备用密钥,而使用PK中的代理EMPLOYEE_NO。
这种模式可以防止你拥有一个管理一个部门并在另一个部门工作的经理,或者一个监督来自不同部门的员工的主管。
如果您不熟悉符号...
...它表示一个“类别”。 在这种情况下,您可以简单地将其解释为员工与经理之间的“1比0或1”关系。
在不详细说明的情况下,我确实向你保证,从长远来看,员工/经理/部门解决方案对于负责维护数据库的负责人来说(首先)是一个真正的PITA(稍后) /或开发其界面。 所以我建议你坚持你的第二个建议。
关于经理/部门关系,主要有两种方式来表示这种关系。 这两种解决方案都授权您保留递归的“经理管理员工”关系,以及可以实施的“经理管理部门”关系,如下所示:
1 - 第一/简单的方法:在部门表中添加经理/员工ID。 该字段当然是员工表的外键
2秒/更复杂的解决方案:添加一个包含以下字段的“经理”表:
Manager id (PK, surrogate)
Department id (FK)
Employee id (FK)
beginningDate
endingDate
你将在哪里存储管理历史:谁,哪个部门,从何时到何时
在这种情况下,不要忘记添加一些逻辑(触发器或客户端控制)来翻译您的业务规则,例如您可以只有一个经理在特定的时间段和特定的部门,任何部门都不能停留超过...没有经理等
编辑:
3 - 更丰富的解决方案将是我的第二个提议的概括,并且可以让您跟踪每个人在公司中的职业生涯。 你可以用一个'作品'表做这个,比如这个(我们在这里称之为“位置”表,我会在这里保留相同的术语:
Position id (PK, surrogate)
Department id (FK)
Employee id (FK)
Position Level (FK)
beginningDate
endingDate
“职位级别”会导致另一个表格持有部门中可能存在的不同职位,其中之一当然是“经理”职位。
该建议与HR数据库和软件中使用的建议更接近,并且您可能不需要如此复杂的解决方案。 但请记住,将人分成多个表格总是一个错误。
编辑:关注你的评论...
为了说清楚,我建议你调整你的字段名称。 我建议你有以下领域:
Tbl_Employee.id_EmployeeManager
和
Tbl_Department.id_DepartmentManager
为此,我们(或任何开发人员)会立即明白id_EmployeeManager参与人员之间的递归关系,而id_DepartmentManager参与人员和部门之间的关系。
回到你的问题,并根据我,你不应该创建以下链接:
Tbl_Department.id_DepartmentManager -> Tbl_Employee.id_EmployeeManager
通过这样做,你意味着有人不能成为部门经理, 除非他已经在管理员工。 有一名员工的部门呢? 那些新创建的部门的经理人员又如何分配? 这是行不通的。 正确的链接应该是:
Tbl_Department.id_DepartmentManager -> Tbl_Employee.id_Employee
您当然可以添加一些业务规则,例如“管理部门的员工只能成为经理”(id_Employee存在id_EmployeeManager某处)或“管理部门的员工无法拥有经理(其中该员工的id_EmployeeManager为null ......)但这些只是业务规则,只要基本规则得到遵守,您的数据模型就可以接受所有规则,这就是说部门由员工管理!
我认为这是最好的解决方案:
经理是管理部门的员工。 您可以通过下一个流程获得递归关系:
员工有一个部门一个部门有一个员工作为经理
也许可以方便地给员工表一个EmployeeType列来定义角色。
链接地址: http://www.djcxy.com/p/70623.html