【问题标题】:Why is a specific cardinality not allowed in the ERD?为什么 ERD 中不允许使用特定的基数?
【发布时间】:2012-09-08 20:31:30
【问题描述】:

在有关实体关系图的每个教程中,我都读到不允许为关系指定固定的基数。只有对 ERD 的非正式评论才能澄清飞行员的数量是exactly 2

因此,例如,每个航班恰好有 2 名飞行员在场的航班和飞行员之间的关系必须表示为:

<flight> 0..N <------> 1..N <pilot>

而不是

<flight> 0..N <------> 2 <pilot>

我的符号是0..N = 可选,很多; 1..N = 强制,很多,1 = 强制,一个。

这个限制是通用的吗?背后的原因是什么?

编辑:澄清了我的符号。

编辑:我可以看到两个关系如何强制执行相同的约束:

         0..N <------> 1
<flight>                 <pilot>
         0..N <------> 1

但是随后查询飞行员是否在给定航班上的查询变得非常难看,因为您必须检查两个属性中的每一个。如果属性的数量增加(例如,增加到 15 名空乘人员),查询将变得完全无法管理,并且架构几乎无法管理。

【问题讨论】:

  • 您的第二个设计没有强制执行相同的约束。特别是,它缺少两个关系中的飞行员不同的约束。

标签: database-design entity-relationship database-schema erd


【解决方案1】:

其他回复提供了一些有价值的答案。还需要添加两块:

首先,ER 建模不仅仅是 ERD。我们倾向于尝试将整个 ER 模型放在一张图上。但完整的 ER 建模远不止适合单个图表的内容。可能存在将关系的基数限制为不少于 10 且不超过 15 的业务规则。但重要的是要认识到这些必须是“业务规则”(即主题规则),而不是出于实际原因施加的设计限制.一个完整的 ER 模型可以包含所有这些关于数据的业务规则,并且在必要时可以用简单的英语表达这些规则。

首选符号 10..15,因为它更简洁,除非需要更多细节来阐明规则,例如规则存在的原因。

以上暗示了需要做的第二点。这是分析和设计之间的区别。如果以经典方式使用 ER 建模,它是数据分析的工具,而不是数据库设计的工具。 “数据分析”是指从以数据为中心的角度分析问题。区分分析和设计,区分问题的特征和解决方案的特征,在正规的 CS 或 IT 教育中教得还不够。把事情做好是绝对关键的。

即使是我们这些意识到差异的人,有时也会将解决方案的特征滑入问题的定义中。这被称为“在盒子里思考”。

如果您想绘制数据库设计图表,请不要使用 ERD。使用关系示意图,前提是您设计的数据库是关系数据库。关系示意图包含 ERD 不应包含的功能,例如联结表和外键。不要将 ERD 用作“关系精简版”。不是这样的。

顺便说一句,另一个答案评论说 ERD 应该可以在任何 DBMS 上实现。这是我刚刚提出的概念的结果,即 ERD 捕获分析而不是设计。

【讨论】:

  • 我说对了吗:ER 模型应该表达我喜欢的任何业务需求。 ER 只处理分析,所以实现还不是问题。理想情况下,ER 建模应该使用足够丰富的语言来表达所有实际业务需求。如果是这样,在我看来EER 将是一个不错的选择,因为它比常规 ERD 更具表现力。当我开始设计时,我知道具体的技术是什么(RDBMS、NoSQL 等),此时我应该使用相关的表示(例如,关系模式)。
【解决方案2】:

基数规则本身只是“任何和所有可能的一般规则”的特例。能够表达“任何和所有可能的规则”的仅有的两种语言是人类自然语言(无论你怎么努力,它的缺点都是经常模棱两可和不精确),以及形式谓词逻辑的符号语言。

如何在数据建模的上下文中使用后者,是这本极好的(且值得高度赞扬的)“数据库专业人员应用数学”一书的全部主题。

Halpin 的 ORM 试图提出一种建模语言,该语言可以覆盖(即用图形符号来表达)比 E/R 更多种类的业务规则。例如,它有用于表达无环图约束的符号(“没有人是他自己的祖先”)。但即使是这种语言也不能表达一切,必须求助于它称为“其他”的最后一类约束,只能用自然语言来描述。

这是一个语言问题。如果您设计的语言具有极少的符号(矩形、连接线、零、一和乌鸦脚),并且只能以极少数的方式组合,那么您就不能指望这样的语言能够表达任何可以想象的东西。

【讨论】:

  • 同意,只是关系表达式等价于谓词逻辑表达式,所以你可以用一个说什么你可以用另一个说。
【解决方案3】:

不是您问题的直接答案,但您可能对如何在实际数据库中实施这种约束感兴趣...

假设您在一个航班上最多可以有 2 名飞行员。您可以简单地创建两个“0..N 到 0..1”的关系:

如果您正好需要 2 个飞行员,只需将 PILOT1_ID 和 PILOT2_ID 设为 NOT NULL(并通过 CHECK 确保它们不同)。


但是,正如您已经指出的,这对于更大的基数很快就会变得笨拙,因此需要使用不同的技术。假设您需要将空乘人数限制在 15 人以内,您可以这样做...

...在联结表上具有以下约束:

CHECK (POSITION BETWEEN 1 AND 15)

请注意,{FLIGHT_ID, POSITION} 上有一个 UNIQUE 约束,如上图中的 U1 所示。

从本质上讲,我们是在每次飞行中将乘务员归类到特定位置。在同一航班上,没有两名乘务员可以占据相同的位置(感谢U1),因此由于每个航班正好有 15 个位置,每个航班不能超过 15 名乘务员。 p>

不幸的是,没有很好的方法来强制所有职位都被填补,因此每个航班仍然可能少于 15 名乘务员。如果这很重要,您可能必须从应用程序代码中强制执行。

--- 编辑---

要寻找一个空闲位置(用于下一个 INSERT),即使它是两个已填充位置之间的“洞”,您也可以执行以下操作(将 1 替换为所需的 FLIGHT_ID):

SELECT DISTINCT *
FROM (
    SELECT POSITION + 1 FREE_POSITION
    FROM FLIGHT_ATTENDANT
    WHERE FLIGHT_ID = 1
    UNION ALL
    SELECT POSITION - 1 FREE_POSITION
    FROM FLIGHT_ATTENDANT
    WHERE FLIGHT_ID = 1
)
WHERE
    FREE_POSITION NOT IN (
        SELECT POSITION
        FROM FLIGHT_ATTENDANT
        WHERE FLIGHT_ID = 1
    )
ORDER BY FREE_POSITION;

此查询可能有以下结果:

  • 它可以不返回任何行,表示所有位置都是空闲的,因此只需选择有效范围内的任何一个即可。
  • 它可以返回行,其中第一个和最后一个可能超出有效范围,因此如果超出,请忽略它们。使用剩余的行之一。如果没有剩余的行,这表明所有位置都已被填满。

这是 Oracle 下的 working SQL Fiddle example,但同样的技术应该适用于任何 DBMS。有更优雅的、特定于 DBMS 的方法来执行这些类型的查询(特别是如果您想要 所有 个空闲位置,而不仅仅是一些),但即使是这种“通用”解决方案对于大多数实际应用来说也应该绰绰有余目的...

【讨论】:

  • 酷,谢谢。我很好奇,第二种方法不会给 INSERT 带来问题吗?假设有一些 DELETE,是否有可能仅使用标准 SQL(没有存储过程)为正在添加的服务员找到适当的 POSITION 值?
  • @max 是的,你需要在INSERT之前找到一个空闲的位置。请参阅我的编辑以了解一种方法 - 它也适用于 DELETE 产生的“洞”。
【解决方案4】:

您有唯一索引(如主键)和非唯一索引: 根据您的唯一键定义允许有 1 条记录或多条记录

然后

您有空字段或强制具有值的字段: 这里你可能有 0 或 1 个值

结合这两件事,你应该能够知道,为什么他们总是说 0 或更多

ERD 不能总是强制规则,规则通常可以由数据库设计强制,但它总是需要软件的另一层(或至少存储过程)

顺便说一句,关于您的示例,如果您在每次飞行中始终有 2 名飞行员,并且您想通过数据库设计强制执行此规则,您可以简单地创建从 Pilots 表到 Flight 表的 2 个关系,是的,您将拥有同一张表的 2 个外键,ERD 允许这样做

【讨论】:

  • 那么说 ERD 试图避免允许太多规则是否正确,以防它们碰巧无法使用准系统关系数据库执行?因此,虽然可以在应用层强制执行任意复杂性的规则,但 ERD 并不是要对其建模?
  • ERD 是通用的,它应该可以由任何 RDBMS 实现,当您进一步研究某个 RDBMS 时,您会发现使用触发器和存储过程甚至表元数据可以更多地执行规则。顺便说一句,我不认为 ERD 试图避免任何事情,您仍然可以在 DB 设计本身中强制或调整一些规则,但肯定不是每条规则。
  • 索引与 E/R 建模无关。有些引擎可以强制执行所有“规则”,而无需任何“附加软件层”。关系与“关系”不同。如果你“建立两个关系”,那仍然不能保证实际上会有两个飞行员。一切,我的意思是这个答案中的一切都存在可笑的缺陷。
  • @ErwinSmout 请发布您的答案,我真的很高兴看到更好的答案。在我的回答中,我尝试使用简单的东西来描述它,我知道 ERD 中没有强制索引,但结果会有一个,我使用 ERD 的物理结果来回答这个问题,是的,如果每个字段的关系是 1..n,我说我可以使用某些 RDBMS 的特性来执行规则,但不是全部,请在像这样抨击我之前仔细阅读我的答案,我会很高兴看到你更好的答案,这是关于这个网站的全部想法
【解决方案5】:

E-R 图表提供了一种方法来指示每个实体参与关系的次数的限制。
实体集和二元关系集之间的边可以具有关联的最小和最大基数:min...max
min1 表示完全参与。 max 值为1 表示最多参与一次,max*N 表示没有上限。
现在来回答你的问题。您的建模一开始就是错误的,因为一名飞行员会参加很多次飞行,而不是您似乎暗示的一次。
此外,如果每个航班恰好有 2 名飞行员并且两者都是必需的,那么这不会被建模为 1-N 关系,而是作为航班的 2 个属性(飞行员 ID),因为它们永远不会为空或可选(不能没有航班2 名飞行员)。
因此,常数的上限表明设计中存在一些问题,这些问题不足以对您的系统进行建模。

【讨论】:

  • 但是N15 的更一般的表示法。你是什么意思确切 15?它们都是强制性的吗?如果是可选的,那么它是直到15N 相同
  • 是的,假设一支足球队正好需要 11 名球员。如果对于我的应用程序来说,哪个球员在哪个位置并不重要,我只需要将他们标记为在一个团队中,我认为为此添加符号会很有用。
【解决方案6】:

我遇到过类似的问题。我的场景是让两支足球队参加一场比赛。所以这两个表是“团队”和“夹具”。在夹具表中,我只有一个“team_home”列和一个“team_away”列。我不确定这是否是最好的甚至是正确的方法,但它对我有用。

您是如何实施 max 解决方案的?

【讨论】:

  • 我刚刚使用了enhanced ER diagram (EER)。如果您查看第一页,您会发现它们有任何基数的符号。更重要的是,我得出的结论是,我的时间太宝贵了,不能花在与符号作斗争上。从现在开始,我只是在 ER 图中添加任何我喜欢的符号,只要我觉得我的同事会理解我的意思。
猜你喜欢
  • 2015-02-19
  • 2013-09-05
  • 2017-05-09
  • 1970-01-01
  • 2014-08-06
  • 2013-05-08
  • 1970-01-01
  • 2017-03-18
  • 2016-10-31
相关资源
最近更新 更多