我有三个实体:员工、项目和角色。员工与项目之间存在关系:员工正在参与某个项目。但是这位员工不仅仅在这个项目上工作,他/她还有一个操作领域,以角色的形式给出。但是,关系不仅仅由属性描述吗?我怎么能做到像“一个员工在这个项目上工作,担任……”这样的描述呢?当然,我可以使用roleId作为属性,就像设计数据库一样,但在ERD中,这是什么关系?
如果每个员工只能在一个项目中担任一种角色:
如果每个员工可以在一个项目中担任多种角色:
两者的区别在于后一版本的复合主键包括职位。由于是所有三列的复合主键,因此值的组合必须唯一,下面的内容是有效的:
project_id employee_id role_id
---------------------------------
1 1 1
1 1 2
在设计数据库之前,我想将问题建模为实体-关系图(使用Chen符号)。在这个图中,我想创建一个员工和项目之间的关系,而不必考虑后续的键和约束。
这是完全可以理解的,也是正确的。纸张是便宜的,数据库中的对象更加昂贵。建模需求并不断改进,直到您有信心,然后再实施。
许多网站的问题在于,有很多木匠,虽然出于好意,但将每个问题视为钉子,并提供DDL,而不是所请求的建模帮助。缺少的是上下文和含义,因此最终结果是具有固定“键”但缺乏上下文和含义的硬性实施。建模允许我们对与我们相关的各种方面进行建模,而不必担心在DDL中看起来像什么。
另一种说法是,OMG已经回答了一个问题如何建模“员工在这个项目上工作为…”?,我正在回答您的整个问题。
在逻辑层面,多对多关系是正确的。这样的关系没有其他考虑在物理层面上呈现为联合表。但是,现在决定这一点还为时过早,因为您仍然在建模关系的上下文和含义。
...也不在SO markdown符号的范围内提供它。 IME,像Oracle Designer这样的工具会在创建实体后生成这些图
胡说八道。建模的整个想法是在编写代码、购买平台或实施DDL之前,使用图表在纸上开发和改进某些内容。该评论仅是关于在事后反向工程现有数据库,许多产品提供此功能。
使用对您有意义的任何符号来建模所需内容。当然,标准符号更具普适性。这里是一个
针对您的ERD
(我不知道“SO markdown符号”如何限制提供预先建模的建议)。我提供了一个可能发生的进展示例。没有什么是“正确”的或“错误”的,这都是纸张;直到您决定哪些元素值得确认,然后才有可能进行下一步进展。
首先,我们从简单的多对多关系开始,你已经知道一些关于它们的信息。尝试模拟一个三方关系是不正确的,这是建模错误:为了解决一个三角恋,你需要首先分别确定每个参与者之间的离散关系;这意味着所有关系都只是双向的。
项目、员工和角色实体很清晰,我们已经了解了一些相关信息。在这里,我没有详细说明主要实体,因为它们是“强”的,而且不是你关注的重点。
进展使用了关系的示例属性,你可以使用自己的属性。(我们的比利时同事已经用文字识别了问题,我只是提供了图片。)人们通常不会做的很多事情,他们应该做;我关心的是真正的建模,从上到下,以便进展并得出正确的数据模型。删除任何无用的东西,并继续前进。
我假设关系的属性证明了实体的存在,所以现在我已经画出了它们。在这里,我使用椭圆形,你可以使用菱形或倒三角形,只要使用一些符号来建模你需要的内容。
现在我们可以清楚地看到:我们不想要Project::Employee::Role,因为那样会允许员工执行任何角色;我们希望只有之前被批准该角色的员工才能被选择。因此,Employee::Role变得更加“强”。
因此,Employee::Role是一个实体。粉色的东西是该特定组合或Employee+Role的子项,而不是所有Employee或所有Role的子项。
同样,我们不希望任何员工在任何项目中担任任何可能的工作,我们希望他们只在批准的项目中担任批准的工作。因此,Project::Role成为一个强身份,并且它已经具有属性了。
因此,Project::Role是一个实体。剩下的椭圆形是该特定组合或Project+Role的子项,而不是所有Project的子项。
我们的粉色子项获得了实体状态,具有特定的属性。更重要的是,它的约束来自于先前受限制的实体,而不是简单的实体。
数据具有自然的顺序或层次结构,按照这种方式绘制的图表更容易理解。现在我们有机会查看属性。它们可能看起来相同或类似或令人困惑;而现在由于上下文和层次结构,它们具有清晰的含义。