考虑这种情况,我正在尝试为公司建模数据库:
Employees
,Managers
,Departments
。Employee
仅适用于1 Department
,而Department
可能有许多Employees
在其中工作。Manager
只能管理1 Department
,同样Department
可能只有1 Manager
。Manager
监督了许多Employees
,但Employee
仅由Manager
监督。现在我有2种方法可以对此进行建模:
第一个解决方案:
考虑到我会保留管理员独有的数据(例如奖金和状态),我会认为Manager
实体继承了Employee
实体。
由于Department
和Employee
之间的关系是1:N
,我会把
Department Id
作为Employee
Works
表中的外键Department
关系。
由于Manager
和1:1
之间的关系是Department Id
,我会把
Manager
作为Manages
Manager
表中的外键Employee
关系。
问题:如何表示Manager
和Employees
之间的递归关系?
第二个解决方案:
我认为不需要Bonus
实体,因为其他Status
也可能有Department
和Employee
。 (实际上我添加了这两个属性只是为了看看如何在两种情况下对其进行建模)
1:N
和Department Id
之间的关系是Employee
,我会把
Works
作为Employee
Manager
表中的外键1:N
关系。Employee Id
和Employee
之间的关系是Supervises
,我会把
Manager Id
作为Manager
Department
表中的外键{{1}}
关系并称之为{{1}}。问题:如何表示{{1}}和{{1}}之间的关系?
问题:
答案 0 :(得分:25)
我可能会选择以下内容:
该模型具有以下特征:
注意:如果您的DBMS不支持延迟约束,您将需要使DEPARTMENT.MANAGER_ID为NULL,以打破可能阻止您插入新数据的循环。
如果要求部门匹配,那么您要么采用DBMS特定的技术(例如触发器或“特殊”约束),要么将DEPARTMENT_ID“传播”到员工的PK中。这种传播最终能够实现匹配:
由于EMPLOYEE_ID必须是全局唯一的,因此它不能与DEPARTMENT_ID一起保留在组合键中。因此,我们将其作为备用密钥,而是使用PK中的代理EMPLOYEE_NO。
此模型可以防止您拥有管理一个部门并在另一个部门工作的经理,或者监督来自不同部门的员工的主管。
如果你不熟悉这个符号......
...它表示“类别”。在这种情况下,您可以简单地将其解释为EMPLOYEE和MANAGER之间的“1到0或1”关系。
答案 1 :(得分:1)
在没有详细说明的情况下,我确实向您保证,从长远来看,员工/经理/部门解决方案是令人不快的(最初),然后是负责维护的人员的真正PITA(稍后)数据库和/或开发其界面。所以我建议你坚持你的第二个提案。
关于经理/部门关系,您主要有两种方式来表示这种关系。两种解决方案都授权您保持递归“管理员管理员工”关系以及“经理管理部门”关系,您可以按如下方式实施:
1 - 第一种/简单方式:在部门表中添加经理/员工ID。该字段当然是employee表的外键
2秒/更复杂的解决方案:添加“manager”表,其中包含以下字段:
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
“职位级别”导致另一个表格持有部门中可能存在的不同职位,其中一个当然是“经理人”职位。
此提案更接近人力资源数据库和软件中使用的提议,您可能不需要这么复杂的解决方案。但请记住,将人类分成多个表总是一个错误。
编辑:关注你的评论......
为了清楚说明,我建议您调整字段名称。我建议您拥有以下字段:
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为此employee是null ...)。但这些只是业务规则。只要基本规则得到尊重,你的数据模型就可以接受所有规则,即部门是由员工管理的!
答案 2 :(得分:0)
我的意见:
表人员,您将为员工和经理添加信息,管理人员也是人,您知道吗? :),你有一个managerId字段链接到经理的Id。
表部门与部门信息
并且,如果员工可以属于多个部门,则创建一个表employee_department来关联它们。如果员工只能属于一个部门而您不需要关系中的更多信息,请在Employee表上添加departmentID字段。
答案 3 :(得分:0)
我认为这是最好的解决方案:
经理是管理部门的员工。 您可以通过下一个流程获得的递归关系:
员工有一个部门 部门有一名员工作为经理
为雇员表提供一个EmployeeType列来定义角色也许很方便。
答案 4 :(得分:0)
如何坚持第二种设计并建立伪关系?
我假设您在Employee实体中有一个department_id
列,用于链接Employee和Department实体之间的关系。如果我们可以假设不会成为管理者层次结构(经理的管理者),我们可以强制执行两个表之间的伪关系,其中Department_ID
用于管理者(Manager_ID
为空)表示他们管理的部门。
只要您清楚地记录这一点,我认为这将是一种节省空间的方法,因为您已经在引用Department实体的Employee实体中有一个FK列(department_id
)。