数据建模:逻辑建模练习

11
在学习数据存储的艺术方面,我一直在尽可能吸收更多的实用信息。PerformanceDBA在以下帖子中发布了一些非常有用的教程/示例,其中包括:is my data normalized?Relational table naming convention等。在这里,我已经提出了这个模型的一个子集问题 here
因此,为了确保我理解他所提出的概念以及其他地方我看到的概念,我想向前迈出一两步,看看自己是否掌握了这些概念。这篇文章的目的就在于此,希望其他人也能从中学习。我展示的所有内容对我来说都是概念性的,是为了学习而不是应用于某个生产系统。如果PerformanceDBA能够给予一些意见,那将非常不错,但我也欢迎任何人给出意见。
作为一个新手,我承认由于缺乏专业知识,我可能并不总是会提出正确的问题,清晰地解释我的想法或使用正确的术语。因此,请记住这一点,并随时纠正我的错误。
如果有足够的兴趣,我想将其从逻辑层面推进到物理层面,以展示整个过程的演变,并在Stack上分享。我会将这个帖子保留给逻辑图,然后为额外的步骤开一个新帖子。为了我的理解,我最终将构建一个MySQL数据库来运行一些测试,看看我所想出的是否真正可行。
以下是我想在这个概念模型中捕获的内容列表:版本1.2进行了编辑
  1. 本网站的目的是列出乐队、他们的成员以及他们将出现的活动,并提供音乐和其他商品销售。
  2. 会员将能够与朋友配对。
  3. 会员可以在乐队、他们的音乐和活动上撰写评论。
    • 每个会员在给定项目上只能发表一个评论,但他们可以编辑自己的评论,历史记录将被维护。
    • 乐队成员将有机会在与其相关的乐队评论上撰写一条单独的评论。作为一个乐队,每个评论只允许一次评论。
    • 会员可以对所有评论和评论进行评分,但每个实例只能评分一次。
  4. 会员可以选择他们最喜欢的乐队、音乐、商品和活动。
  5. 乐队、歌曲和活动将按其类型进行分类,如果必要,将进一步细分为子类型。一个乐队或活动可以属于多种类型/子类型组合。
  6. 给定乐队的活动日期、时间和位置将被发布,会员可以表明他们将参加该活动。一个活动可以由多个乐队组成,在同一天的同一地点可以举行多个活动。
  7. 每个派对都将与至少一个地址相关联,并维护地址历史记录。每个派对也可以同时与多个地址相关联(即账单、发货、实际地址)。
  8. 乐队、乐队成员和普通会员将有存储的个人资料。

所以这就是它,可能有点复杂,但希望随着过程的演变和社区的输入,它可以成为很好的学习工具。有任何建议吗?

alt text

编辑v1.1 回应PerformanceDBA:

U.3)这意味着数据库中除了乐队商品之外不能有其他商品。正确吗? 那是我的最初想法,但你让我开始思考。也许该网站想要销售自己的商品甚至是乐队的其他商品。不确定是否需要修改整个目录部分还是仅存在于乐队之间的识别关系? 尝试对完整专辑或歌曲进行销售的修改。无论哪种方式,它们都只能以电子格式提供下载。这就是为什么我将专辑列为由歌曲组成而不是两个单独的实体。

U.5)我了解您提出的有关“Favorite”的循环关系。我想达到这个“它只是一个实体,具有某种形式的差异(FavoriteType),以标识其处理方式”,但我不清楚如何做到这一点。我在这里错过了什么?

u.6) “业务规则这可能是你唯一不擅长的领域。”
感谢诚实的回答。 我将重新审视这些内容,但我希望通过我已经回复给你的问题来消除我的困惑。

Q.1) 是的,我希望有接受、拒绝和阻止功能。 我不确定您所说的如何改变逻辑模型?

Q.2) 一个人不必成为用户。 他们可以仅作为乐队成员存在。 这就是你在问什么吗?

小问题

零个,一个或多个……哎呀,当我构建模型时,我承认我忘记了关注这个问题。 我将按原样提交此版本,并将在以后的版本中解决。 我需要更多地了解约束检查以确保我理解正确。

M.4) 取决于您是否预计未来会购买订单。 您能详细解释一下你的意思吗?

alt text

EDIT V1.2 针对PerformanceDBA的输入做出的回应...

所学到的教训。

  1. 我混淆了识别/非识别和基数的概念(即流派/子流派),并且这还不一致,使事情变得更糟。
  2. 逻辑图中不需要联接表,因为它们的多对多关系可以在物理模型中描绘并扩展。
  3. 我忽略了许多关系中的基数重要性。
  4. 使用有效动词短语阅读关系的重要性,以确保我正在建模想要实现的内容。

U.2) 在此模型概念中,仅需要将场馆追踪为事件的位置。 不需要收集其他数据。 话虽如此,事件将在给定的事件日期举行,并将在场馆举办。 场馆将举办多个事件,可能在同一天举办多个事件。 在我的新模型中,我的想法是EventDate已经与Event绑定。 因此,Venue将不需要与EventDate建立关系。 在U.2)下列出的第五和第六个项目让我质疑我的想法。 我有遗漏吗?

U.3) 是时候将Item和Band之间的链接移至Item和Party了吗?根据当前的设计,我看不到出售与乐队无关的商品的可能性,正如您提出的那样。

U.5) 我按照您的建议保留了原样,而不是将其作为离散的上/下级关系,因为我认为没有这种类型的卷起的好处。

其他修改

AR.1) 经历了FavoriteItem的练习后,我感觉需要将Item to Review建立多对多的关系来指示。这是必要的吗? enter image description here

好的,我们开始v1.3

我花了几天时间来回反复设计这个版本。 一旦逻辑过程完成,因为我想知道自己是否在正确的轨道上,我会深入研究我所学到的东西以及初学者在这个过程中面临的困难。 这个版本的重点是通过加入一些键来帮助看清楚我过去缺少的东西。 做矩阵的过程证明也非常有帮助。 不管怎样,如果不是PerformanceDBA提供的输入,我仍然是一个迷失在黑暗中的灵魂。 谁知道我的当前设计可能会再次确认我仍然是这样,但我已经学到了很多,所以我知道我至少手里拿着手电筒。

此时我承认我仍然对识别和非标识关系感到困惑。 在我的模型中,我不得不使用非空的非标识关系来连接我想建模的关系。 在阅读很多关于此主题的文章时,似乎对此事有很多分歧和犹豫,因此我在我的模型中做了我认为代表正确事物的事情。 什么时候强制(标识)以及何时自由(非标识)? 有任何意见吗?

enter image description here

编辑v1.4

好的,采纳了V1.3的意见并清理了一些东西,现在发布此V1.4

目前正在制作V1.5来包括属性。

enter image description here

编辑v1.6

好的,自从我在这里发布过帖子以来已经过了一段时间,但是这个项目的工作仍在进行中。 现在发布V1.6,其中包含与V1.4的最后发布相比进行了许多更改。 此版本显示了键的进一步演变。 它仍然不包括属性或任何AK或IE。 我已经开始着手物理模型,并利用它来帮助解决属性问题,并尝试解决定义AK和IE时遇到的问题。 逻辑模型的下一篇文章将包括这些键和属性。

enter image description here


2
我不确定问题是什么。 - Larry Lustig
3
@Larry. 它比奔跑吧!兄弟小,比吉利根岛大。 - PerformanceDBA
2个回答

10

方法

我会涵盖具体细节,但只会完全涵盖一两个学科领域,而不是全部。您可以将其应用于所有学科领域。

我还没有回答核心学科领域,因为我们仍在处理实体识别。解决了这个问题后,Reviews等将更容易;交易实体取决于识别实体。

方向

D.1) 我知道我说过需要看整个模型。有一个例外情况。历史、时间或审核数据(例如编辑和存储的版本)。在这个早期阶段,它们可以被搁置;在逻辑模型完成之前实现。这是承认它们是某个父级的简单依赖项(a),必须先将父级与所有其他表建模相关(b),以排除不必要的复杂性(c),从而使我们集中精力处理相关领域。

  • 特别是,您可以忽略动词短语中的时态(否则每个版本表的位置都需要Has/Had)。现在保持现在时态,因为重点是建模,而不是归档。

未解决的问题

U.1) 可选父级
这是完全不允许的。不仅是由IDEF1X,而且由任何完整性概念都禁止。如果定义了FK引用,则必须存在父级。要允许可选父级,必须删除FK引用(或不实现)。这种情况将根据定义排除结果作为“关系数据库”的资格。例如:Address:Order

当然,在发达国家,Order 必须有一个 Address 以符合法律或税务原因;这是与标准要求无关的问题。
U.2) 活动
Party::PartyAddress 是正确的;Address::PartyAdress 也是正确的。但 Event::Address 需要进行改进。地址是一个识别参考表;如果使用了它,它将成为父级,Event 将成为子级。我留给你来确定/建模多个位置的 Events,以及在一个或多个位置的 Events
  • 可能涉及到场馆。或者是 EventOccurrence

  • 但如果这是一个在多个位置发生的普通事件,则不需要实体,Address 已经在 Order 中了。

U.3) 假设 Catalog 是传统意义上的条目(JCPenney 2011),即出售或租赁的物品清单。

  • OrderSaleItem 是正确的。

  • 关键点。 Catalog 是 Dependent,只能作为 Asset 在 Band 的上下文中存在。很好。这意味着数据库中没有其他商品,只有乐队商品。是正确的吗?

  • 我可以看到 "Evening performance with the Blues Brothers" 是一个可以订购、开票和支付的事件。还可以进行评论等操作。

  • 我不知道 Song 如何适应其中。乐队是在销售专辑、歌曲还是两者兼而有之?

  • 难道没有其他乐队商品:音乐会/活动纪念品;海报;刻有标志的小酒杯吗?

  • 与您提及的命名约定和数据库的其余部分一致,Catalog(内容)应该被命名为 Item(行)。您已经(自然地?)在 OrderSaleItem 中使用了它,而不是 OrderSaleCatalog

U.4) Genre

  • 一个 Item 通过多对多的 Genres 进行分类 没有问题。

  • 我认为另外 一个 Genre 分类多个 Items。关系是一对多的(将在物理上解决为联合表)。

U.5) 喜爱的
Item::Favorite 的基数被颠倒了。当你纠正它时,Favorite 主题区域将需要进一步建模。

  • 实体之间的循环关系或双重路径是未解决模型的信号。通常一个是正确的,而另一个是多余的。(有例外情况,但不在这里; 当发生这种情况时,动词短语会区分它们。)

  • Band::FavoriteItem::Favorite 二者中只能正确一个。

  • Item::Favorite 似乎是正确的,因为 Band 已经在 Item 中被识别出来了

  • 同样地,为乐队和商品设置一个 Favorite 实体并不牢固。单个 Favorite 实体中的每个标识符都是一个 Party。当规范化时,它将会破裂,最好在此阶段要求明确标识符。 它可以是一个带有某种形式差异(FavoriteType)的实体,以确定其处理方式;或者一个用于乐队和另一个用于商品的 Favorite,在这种情况下不需要差异化,消除了歧义。

U.6) 业务规则 这可能是你唯一薄弱的领域。总体反应,你已经分别完成了任务(所有建模与编写BRs)。它们不符合模型。在进行下一个周期时,将业务规则作为指令,并同时调节它们,就像实体、关系和动词短语一样。

问题

Q.1) 用户/朋友
你已经完美地掌握了它的本质。以及关系的基数。(对此进行全面处理。)这对于已接受的Friend是正确的。

  • 因此时态应该是过去式(跟随大多数行)

  • Requested和待处理的Accepted是少数。可以在IsAccepted位或布尔值中轻松实现。

  • 稍后您可能会有IsRejectedIsBlocked(后者应该是单独的实体)。

  • 这是您需要的吗?

Q.2) “人是零到多个用户”的基础是什么?

小问题

M.1) 只使用单数。

M.2) Party Has zero-to-many Addresses。我认为他们必须有一个地址才能进行交易(但可能不是所有的Users)。

M.3) 订单可能有零到多个付款。"需要"意味着第一个Payment必须与Order同时插入。

  • 同样,对于任何强制性子项(一对多而不是零到多),第一个子项必须与父项同时插入。这通过企业数据库中的事务完成,因为实现了立即约束检查(而非延迟),而小镇上的人们则为了傻事情争吵,例如延迟约束检查更好,并且花费他们一半的生命来弄清楚如何不被陷入他们创建的无限循环中。MySQL根本没有这些,所以对于此实现没有什么可担心的。

M.4)OrderSaleItem应该是OrderItem或者Order应该是OrderSale。这取决于您是否预见将来会有OrderPurchase

主题区域示例

对于不熟悉关系数据库建模标准的读者,可能会发现IDEF1X符号很有用。

如上所述,我不提供完成的数据模型,仅提供指导。这只是一个选定主题领域的进展。它并不完全正确或完整。
您的动词短语很好。我提供了一些备选方案供您考虑,它们并不是“正确”或“更好”。您需要选择一个进展或自己的进展。目标是在每种情况下最简明准确地使用动词短语。
没有建议认为“Person”是正确的,“User”是错误的,这要等待您的答案。但是我必须在模型中使用一些东西;由于您已将它们建模为单独的内容,对立面可能很有趣进行评估。
因此,请继续推进模型,然后再发布(只需编辑问题,保留标题段落并替换其余部分)。
V1.1和响应
那肯定是一个进步。
我已经以伪法律格式重新编号了项目,包括章节标题,以便我们可以始终保持编号并继续添加。实际上,这确实缓解了SO编辑问题。
U.3)是否需要对目录部分进行整体改造,还是只需要存在与乐队之间的识别关系?
  • 不行。在这个层面工作的好处就在于,你所做的决策将成为数据运行的铁路轨道,作为货物运输或者不运行(因此需要替代的传输和大量代码或者额外的数据仓库来推导)。而且这里的决策是廉价的(建模时间,纸张)。

  • 现在,一个项目只存在于乐队的上下文中。它是有依赖性的。为了允许非乐队商品,它需要独立。然后现有的超/子类型集群需要重新设计。

尝试修改以销售完整专辑或歌曲。无论哪种方式,它们都只能以电子格式下载。这就是为什么我将专辑列为由歌曲组成的原因

  • 好的。但现在你只能出售专辑,不能出售单曲。

而不是两个独立的实体。

  • 不确定你的意思(你确实有两个独立的实体)。

  • 看起来你还没有看到我的Subject Area Example。请注意,如果你现在打开它,它包含了我添加的一些内容V1.1;我没有改变昨天的V1.0响应。

  • 实际上这意味着你应该再次查看我的V1.0答案,同时查看示例。

U.5) ...但我不清楚如何做。我错过了什么?

  • 具有差异化的一个实体示例是任何一个超类型/子类型集群。收藏夹是超类型,BandFavourite和ItemFavourite是子类型;允许每个引用到Band xor Item。

  • 你已经建模了ItemFavourite。现在的问题是,ItemFavourite的事实是否意味着Band是喜爱的;或者BandFavourite是一个离散的事实?在示例中,我建模了后者,没有使用Favourite::ItemFavourite/BandFavourite结构。

Q.1) 是的,我想要Accepted、Rejected和Blocked。我不确定你所说的会如何改变逻辑模型?

  • V1.0无需更改(我已经说明它非常完整),但您可能需要一个额外的实体。

  • 您需要在Friend中添加三个位或布尔指示器。这将服务于以下状态:

  • 请求(但未接受)

  • 请求和接受
    .

  • 但是,被阻止的不是朋友(或者以前可能是朋友,但自从被阻止以来就不是了)。因此,要么实体名称必须更改以反映这一点(对两个关系没有更改),要么Blocked必须是一个单独的实体。第二个关系的两个分离含义会导致复杂性,因此我会选择后者。

通过前者,我们有了其他状态:

  • 已阻止
    .
  • 然后动词短语需要更改(为了清晰起见,我将包括RoleName),其中一个具有替代含义。
  • (在属性级别模型中,这将更加清晰,这就是为什么我们用图片建模而不是文字;因此我已经包括它。)

问题2)一个人不必成为用户。他们只能作为BandMember存在。这就是你在问什么吗?

  • 不。为什么我们需要区分Person和User?有哪些单独的操作或属性?到目前为止,我将Person和User视为相同的实体;Person是没有活动的用户。

  • 这是最后一项,阻碍我们处理核心主题领域的事项。

M.3) 我需要更多地了解约束检查,以确保我理解得正确。

  • 现在不用担心这个问题。我只是给你一个简单的理由(不兼容的SQL数据库似乎使事情变得简单,但实际上它们使事情更加复杂)。MySQL没有这些能力,所以你可以排除考虑平台,并且只需有意义地对模型进行基数建模。

M.4) 这取决于你是否预见到未来会有OrderPurchase。你能详细说明一下吗?

  • 在模型的背景下,你提供了结构来制作销售订单(物品)。因此是Item、Order和OrderItem。

  • 但如果你也提供了跟踪采购订单的结构(购买物品以及办公用品、租金等),那么你需要区分销售订单和采购订单。因此:

  • Item

  • OrderSale和OrderSaleItem

  • OrderPurchase和OrderPurchaseItem

版本1.1

U.2) 事件进展

  • EventDate看起来不错。我会将关系定义为Event Was Performed On EventDate

  • 而ItemGenre是完美的,但Event::Venue需要改进。这是您一贯犯的错误,因此需要解释。

  • 您正确地对Venue进行了建模,它是独立的,并且存在于Event的上下文之外。但是,Event May Be [Held] At zero-to-many [Independent] Venues是不可能的。

  • 活动在许多场馆举行,场馆也举办许多活动。如果只有这些,由于这是逻辑级别,您可以绘制多对多关系,然后完成。在物理级别上,该关系通过实现联合表来解决,其PK是两个父PK,没有数据。(Enemy是一个很好的例子。)

  • 但是,如果有数据(例如,您需要跟踪日期或参与者人数等),则它不是联合表,而是另一个实体。在Event和Venue之间发生的事情。

  • EventDate是一个很好的候选项。我们已经有了那个日期。只需添加Venue并搅拌即可。我会将在Event和Venue之间发生的事情称为Performance。

  • 同样,EventAddress已经进展,但尚未完成。

  • 活动有地址还是场馆有地址?(对其进行建模,无需用语言解释)

  • 如果是场馆:您需要场馆的所有历史地址(例如Party),还是只需要当前地址(例如Order)?

M.5) SubGenre. 请解释为什么SubGenre是(a) 独立的,以及(b) 关系是非识别的。

M.6) Item Is zero-to-many Favourites. 因此:Item Is a Favourite of zero-to-many Users。同样,Each User Chooses zero-to-many Favourites。因此,Each User Chooses zero-to-many Favourite Items

V1.2和响应

进展很大。

U.2) 事件继续发展

根据您的编辑以及新要求,有些是可以的,有些不可以。数据模型的所有其他主题领域基本上都已经完成(对于逻辑而言),但这一领域却很混乱,远没有解决。部分原因是由于添加了要求(没有抱怨,在现实生活中会发生这种情况;问题在于如何处理它)。

我要在这里提出的主要观点是,数据模型应该始终建模真实世界,而不仅仅是业务需求。这样做可以(a)使DM免受变化的影响,(b)为添加的要求提供坚实的平台。这并不意味着您必须建模整个真实世界,但您建模的部分必须反映现实,而不是被压缩以满足要求。

其次,有关事件、乐队-事件、表演等之间的区别缺乏清晰度。现在,事件是Party-Band-Item-Event。这很好,但它不适用于新样式的事件要求。

第三,在Party和Order方面,您对地址有很好的掌握,但在Venue方面却没有。

  • 由于您接受标准兼容模型和处理方式,因此地址是一个参考表。

  • 它是独立的(方形角落)。

  • 实际上,您可以将地址和位于其上方的所有内容放在第一页上;使这部分成为模型第二页,并仅在此页面上使用地址。

  • 正确建模:Party有Addresses的历史记录。根据正在执行的任何活动,他们必须至少有一个当前的{IsBilling | IsShipping | IsPhysical}地址。

  • 正确建模:订单有一个IsBilling地址(如果需要IsShipping,则需要添加单独的关系)。

  • 地址不是Venue的子级(也是独立的,正确的)。我认为会场不会位于零到多个地址中。(也许这是旧的基数反转错误,但由于其他关于事件和场馆的混淆,我不确定。)

  • 实际上,Address :: Order是可疑的。(Q.3)您是否希望订单引用任何有效地址,还是针对执行订单的Party的特定地址?

  • 回到事件。接受声明的EventDate。那很好,但评论等适用于通用音乐会,而不是他们在蘑菇上表演的单个音乐会。选择V1.3。

  • 您关于事件等术语与要求等的一致性,但不支持所述要求。

  • 因此,让我们开始按照现实世界中使用的方式使用“Event”,并将其建模。我们一直称为“Event”的Party-Band-Item实际上是Performance。而不是计划的通用性能,而是在特定场地进行的单个性能。

  • 这是您使用EventDate的意思,或者EventDate解决了Performance。

如果你不介意的话,我会避免打一千字,给你一张图片。主题领域示例 V1.2 注意,每个事件中的多个乐队已经解决了。
动词短语直接来自天堂。一个地址托管多个场馆,每个场馆提供多个事件,每个事件有多个表演,每个表演都是一个聚会乐队项目。
U.3) 是不是该将项目和乐队之间的链接移到项目和聚会上呢?根据目前的设计,我看不到销售与乐队无关的商品的可能性,正如你所提出的。
首先,我们需要使用关系术语,不是因为我是个学究,而是因为真正的专家说这真的有助于过渡到关系世界。
其次,我们不能通过“移动关系”来实现这一点。
你必须对非乐队商品进行建模:你要如何销售它;如何跟踪它;如何收款。无论你是否想要评论和回应等。我不明白聚会与此有何关系,而且现在我们正在销售乐队商品,而不是聚会商品。请考虑引用完整性问题。
版本 1.2

AR.1) 经过FavoriteItem的练习,我觉得Item to Review需要一个多对多的关系,因此需要指定。这是必要的吗?

  • 在V1.1中,一个Item有很多评论,而一个评论只涉及一个Item。一个人可以产生很多评论(每个Item一个评论)。这是合理的。

  • “一个评论涉及多个Item”是不合理的。

  • 如果有什么问题,现在FavouriteItem/FavouriteBand已经解决,Review也需要相应的解决和区分:我们需要区分BandReview和ItemReview吗?好/坏的ItemReview是否表示好/坏的BandReview,还是它们是离散的?

  • 一个评论(目前)不能同时涉及Band和Item。这意味着两个外键,其中一个将为Null,而Null FK是不允许的。Item和Band已经有了区别,这种区别是成熟的。

  • ItemReviews可以进行总结等,但那是另外一回事。

U.7) 这留下了一个新问题需要解决。如果评论可以涉及乐队或专辑或歌曲或表演,我们如何确保引用完整性。我们不需要AlbumReview引用SongReview等。对其进行建模。

R.5) 该模型目前在项目层面提供了音乐类型 (Genre),意味着专辑和歌曲可以用此标记。(可以通过 CHECK 约束禁止商品使用此标签) 但没有对乐队进行分类。考虑到(a) 乐队会随时间变化,(b) 在项目层面进行此类分类更加精确,以及(c) 可以从他们的专辑或歌曲中轻松推断出乐队类型,这可能足够了。

  • 如果需要单独对乐队进行分类,你需要添加此功能。

  • 那么活动类型 (Event Genre) 呢? 如果需要,我认为每个活动只能有一个类型。

  • 请记住,像场馆和音乐类型这样的表格是主要数据库中的重要搜索条件。它们也是分析向量。

  • 数据仓库团队需要将其添加为事实表的维度;在正确建模的数据库中,它们已经作为事实表的维度存在。 展示所有安排了"Folk Music" 活动并吸引超过10,000人的场馆非常易懂。

  • 讨论点。 不是说上述内容不正确。 我在数据库和iTunes中发现,精确性很重要。为什么要让Genre::几个东西,而不是Genre::具体的东西? 如果你只有Genre::Song,并且歌曲仅有一个类型,那么专辑和乐队就是精确的合并结果。现在我们拥有的方式取决于数据录入人员的音乐知识,并且 Genre::Thing 是多种多样的,所以它非常松散。Genre :: Song 则更加精确。

R.6) 没有对"members can show that they will be attending the Event"进行建模。此外,需要澄清兴趣、预订和出席之间的区别。

R.8) 没有进行建模。

M.3) 该问题已关闭,但动词短语保持不变。

M.7) 逻辑模型与关联表。现在该问题已关闭,应删除逻辑模型中的任何关联表;任何剩余的表(两个父表之间)都将包含数据。这意味着需要遍历所有从属表并删除没有数据的表。因此,V1.3 应更简洁。

M.8) 项目 OrderItem。

M.9) 现在 Party-Person-User 已经解决。独占子类型结构需要一个鉴别器,并且约束将用于强制执行完整性。当存在多个时,PartyType 是最好的选择。但是对于只有两个的情况,列 IsBandIsPerson 就足够了。

M.10) 您已经纠正了基数反转错误,但某些动词短语仍然朝着错误的方向进行。

27 Jan 11

实际上,如果我们进入逻辑键/属性级别(而不仅仅是实体关系级别),很多这些问题会更清晰。现在是时候这样做了。例如:

Q.3) Order:Address 是可疑的。约束条件不完全正确,因为这将允许订单拥有任何地址,而不是特定于执行订单的 Party 的地址。

但是由于你是MySQL,没有引用完整性,可能不知道在真正的SQL中如何完成,因此我将提供FK定义,这也是RI约束。希望你能理解我的简洁陈述,这些基于RM,规范化并由SQL支持,当你没有SQL时,这有点不公平。

  • 为了使两个约束都成立,由于Party必须在每个约束中相同(只有一个Order.PartyId),因此只允许属于PartyId的PartyAddress子集。

地址资格示例

续第二部分...


3

...第二部分 V1.3和响应

所有问题都是次要的,或者涉及到您正在学习的新步骤。

标识符 vs Id列

我不会在这里给出完整的解释,因为我已经至少发布了20篇关于如何使Id列瘫痪数据库并剥夺其关系能力的帖子。我将仅在此问题的上下文中处理此问题。

  • 这里是一个示例,首先详细查看问题。请注意,马克很有能力,但完全被卡住了。然后阅读我的答案,再查看数据模型。(现在就这样做,它提供了上下文)

  • 思路是,将数据建模为数据,我们正在这样做,您将得到一个数据库,或者将Id列添加到所有移动的位置上,这妨碍了建模练习和规范化,并且您最终将得到一堆互相“链接”的电子表格,存在大量重复而且无法高效运行。

  • 因此,请从所有表格中删除所有形式为[Table]Id的列(保留迁移密钥,它们是正确的),除非以下表格(这些是在整个数据库中反映的重要标识符。请注意,ERwin将更正所有子级、孙级等表格:
    Party
    Address
    Item

关系/IDEF1X标识符

您正在学习标识符。这些是自然键。用户使用的键或已从父级迁移到子级作为外键的键。因此,它们不仅标识关系,还标识子级。您的姓氏不仅告诉我关于您,还告诉我关于您的父亲,并且您也是您父亲的儿子。想要使其唯一?没问题,只需添加名字即可。

您一直在阅读我的答案,查看我的数据模型,然后向您的模型中添加标识符。它比那容易多。 ERwin(因为它实现了IDEF1X)可以为您完成此操作。

  • 考虑到 Party、Band 和 Person,Party 的标识符是 PartyId
    (好的,那是一个代理键,不是自然键;但是自然键 Lastname, FirstName,BirthDate 等非常长,如果我们使用它作为主键,则会被迁移到子级、孙子级和重孙级,这是不可取的,因此我们添加一个短的代理键,并将其作为主键)

  • 当你在 ERwin 中创建子类型并指定关系时,它会自动将 PartyId 放在 Band 和 Person 中,作为 PK;它会标记它为“(FK)”。(注意:我在我的模型中使用粗体字表示(FK)。)

  • 就这样,你完成了。Party::Band 是 1:0-1,Band 主键是 PartyId。由于它是子类型,ERwin 将确保关系是识别的,因此父 PK 最终出现在子 PK 中,依赖子有圆角。

  • 如果没有子类型,情况将相同,除了关系可能不是1::0-1,它可以是1::1-n。在这种情况下,您需要添加另一个元素使其唯一,例如 fFirstNameSequenceNo

  • 并且您必须告诉 ERwin 您想要一个识别关系。(如果不这样做,它就是一个普通的 FK,列将在下面;表将是独立的;角为正方形)。

  • 如果在某个时候您决定使用那些 FK 列来形成 PK,则只需单击关系并将其从非识别更改为识别;列将被移动到上面;角将为圆角。

角色

  • 现在进行下一步。我们知道Band::Party是1::1;Band是Party的子类;Band.PartyId是完美的PK(不需要Id列)。Person也是如此。但它们都是愚蠢的名称,或者换句话说,Band实际上是与Person不同的角色,并且它们都是Party。因此,我们想要清晰地标识这个角色。

  • 在Band中,我们希望将PartyId称为BandId,以反映其角色。编辑子类型符号和子项之间的关系,而不是表格。在对话框中,填写RoleName为BandId。就这样。你完成了。

  • 因此,以下更改从...到:

    FloorItem.ItemId       FloorItemId
    BandItem.ItemId        BandItemId
    因此...
    Other.BandItemId       OtherId
    Album.BandItemId       AlbumId
    Song.BandItemId        SongId
    Performance.BandItemId PerformanceId

  • 删除所有[Table]Id列将使以下表格没有PK。现在,将Name列添加为PK。您可以告诉我用户想要哪些自然键作为这些表的标识符: Event
    Genre

  • PartyAddress是一个例子(即正确建模),说明了我上面讨论的所有内容。它没有PartyAddressId。PartyId和AddressId一起形成PK。两个关系都是Identifying。

Identifying vs Non-identifying Relations

在这个主题上,阅读了很多文章,似乎存在很多分歧和犹豫不决的情况。

  • 是的。不幸的是,现在任何有键盘和调制解调器的人都可以“发布”。人们发表意见作为事实;他们对自己毫无头绪的主题发表荒谬的言论。这会让试图学习的人感到困惑。

  • 这是科学,而不是魔法或黑色艺术,也不是意见。

  • 在学习时,只阅读定义,并仅听那些清晰地传递科学的人(而不是那些混淆或将科学视为艺术或受意见影响的人)。我们正在学习事实、物理定律,而不是关于定律的意见;定律对每个人都是相同的,在全球范围内都适用。你无法从认为事实是意见的人那里学到东西。

让我们从头开始:

  1. 关系是定义标准(使子级独立/依赖),而不是反过来。

  2. 一个关系始终是子表中的父表PK的FK。

  3. 识别关系中,该FK是PK(或PK的第一部分,如果PK是复合键)。子表是一个从属表。

  4. 非识别关系中,该FK是非PK列,子表是独立的(它可以被其他关系强制变为从属)。

  5. 所有子类型都有从超类型的识别关系。否则,它们将不是子类型,而是超类型的独立部分。

  6. 所有1:0-1关系都是识别关系。

所以我按照我认为正确的方式进行了建模。

  • 这可能就是你最终添加[Table]Id键的原因。

何时强制(识别),何时自由(非识别)?

  • 永远不要强制任何建模(数据库和功能),特别是数据方面。我们想要管理、控制、塑造、控制等不可控因素。但要有效地做到这一点,我们必须首先了解它。强制其会使其无法暴露自己,也会使我们无法注意到其中的细微差别和风味(因为我们“知道”它)。让它自由,但受限,就像围场中的马,而不是囚犯在马厩里。

这就是为什么在每个电子表格上添加Id列会阻碍对数据的理解,从而阻碍对其进行任何建模。

  • 如上所述,识别或非识别是关系的特征;而实体是否独立与否是其结果。

按照关系/IDEF1X/ERwin样式进行操作:

  1. 你需要一个实体,就画一个实体。给它命名。除非它是画布上的第一个实体,不要添加键

  2. 现在考虑它的关系。你已经建模的实体与这个新实体有什么关系?画出那个关系(关系是从父级到子级绘制的)。

  3. 当然,默认情况下是识别关系,因为大多数关系型数据库中的关系都是识别关系。将父级PK放置在子级PK中。

  4. 如果你认为,“不,我想让它独立”,那么你最好有一个很好的理由。关键问题在于,这个实体是否完全独立存在,是否存在于其他独立实体的上下文之外?在你的模型中,我认为有五个:
    地址
    聚会
    物品
    事件
    类型

每个其他实体都只存在于这些独立实体的上下文中。因此,你绘制了识别关系,因此它们都是依赖关系。

  • 回忆一下,我们之前把物品作为独立实体;然后我们有了一个新的形式的物品;这使得旧的物品成为了乐队物品;这使得乐队物品依赖于新的物品。

  • 我们在ItemId中有一个很好的标识符,它不仅在(当时的)物品集群中存在,而且在OrderItem、Review等中也存在。

  • 我们改变了物品的上下文(创建了一个更高级的物品),由于识别关系,那个然后在整个模型中迁移,并且新的乐队物品也在其上下文中迁移。

  • 新的ItemId仍然是一个很好的标识符。BandItemId正是ItemId,但扮演着特定的角色,它是ItemId的子集/子类型。

  1. 所以如果它是真正独立的实体,就给它一个新的PK。
  • 在这个阶段,我们需要一列不是Id的列,而是有意义的可以识别实体的列,比如Event.NameCustomer.Code。没有人会把顾客称为123456这个编号,他们会想到“IBM”、“3M”等等。随着模型的发展,我们将确保拥有真正好的主键;但现在对于新的实体,我们只需关注它是否有标识符。

  • 例外情况:对于地址、派对和物品,您知道在V1.0时将会有数百万、数千个和成千上万个;这些都是主要的标识符,将在整个数据库中进行迁移;真正的PK非常长;因此,您需要一个短的Surrogate Key作为PK;所以您从一开始就设置了这个,并且我对此没有异议。

    • 如果您已经准备好使用Domains,则使用INT、INTor SMALLINT、SMALLINT。

    • 否则,使用Name,CHAR(30)。

  1. 下一步是完成新实体的主键。如果父级的基数是1::n,则它已经具有父级的主键,只需添加一个元素使主键唯一即可。让我们看看订单。它已经有了PartId,因此OrderNo可以在PartyId内部。只需更改PK列的顺序为(1) PartyId,(2) OrderNo

  2. 唯一需要进行一点强制的情况是,当形成PK的列数过多,或者PK的总宽度过宽,无法作为FK迁移到子级时。然后,我们仅在这种情况下创建附加的Surrogate Key,形式为[Table]Id(它们始终是附加的,我们不能失去真正的PK或唯一性,因为它支持其他要求)。

  • 据我所知,这个魔法数字是七(实际上是许多事情的魔法数字;即使这个项目也出现为第七项),并且最大宽度为30个字节。这已经在地址(已经高度优化)、派对(否则为64个字节)和物品(超过30个字节)中从一开始就完成了。

  • 如果我们要打破内在的关系能力,我们需要承受这种关系能力本身的痛苦非常严重,并且没有其他原因。在您的模型中甚至没有接近这一点。

审核集群

您做得非常好,所以考虑这作为下一个进展。基本上,您有两个选项,当然我们正在将其与Item集群进行比较/关联。

  1. 保留现有的Review cluster。我们需要一个SongReview和一个AlbumReview。并且去掉ItemReview(它封装了所有项,这意味着我们在重复)。我认为我们排除了非乐队物品的评论。

  2. 允许非乐队评论针对任何乐队物品,例如,将ItemReview FK从Item更改为BandItem。这样可以将所有BandItems封装在ItemReview中。去掉PerformanceReview。

  • 当然,您可能不希望对BandItem.Other进行评论;可以通过其他方式加以限制。但是如果您想严格执行,则需要(1)。

颜色

很高兴您采用了我的配色方案。

  • 这种意义和视觉相关性在小型模型中(大多数我的SO模型)不会显示出来;它只会在像您这样的大型模型中显示出来。

  • 由于您在V1.3上做得非常出色,因此我为您创建了一个ERD。实际上,值得再次阅读IDEF1X符号文档,它非常简洁,我被告知人们在建模后阅读它时会获得更多价值。我需要知道的是,自然层次结构和颜色对您是否有所帮助。

  • 这只是完成实体级逻辑。

您可以继续进行逻辑、键级(唯一属性为FK,我们知道它们是什么)。但是请随意开始识别属性(在这种情况下,显示属性级别)。

可选列

U.1) 可选父项已重新出现在模型中。PartyAddress is shipped for Order不可为空。

  • 如果您打算将送货地址建模为可选的,则需要一个OrderShipAddress实体,它是Order的子级,基数为1::0-1。

  • Null(可选列)就像癌症一样在身体上收集,可空FK(可选父项)就像五岁以下孤儿的喉咙癌一样。

  • 这是处理任何可选列的基本方法,不限于此处的FK(可选父项)。

轻微

M.11) 这些在V1.2中是正确的
Review::Comment 为 1::0-1
BandMember:: Comment 为 1:0-n

M.12) Event::Person 为 n::n(而且这些列将不会在逻辑级别上显示)

V1.4 和响应

进展非常顺利。你对标识符和键满意吗?

U.8) (如果你先做这个,其余的就会变得容易。) ERwin 的限制。恭喜你,你已经创建了一个达到了ERwin 在逻辑建模方面能力极限的模型。明确地说,这并不是真正的限制,因为它在物理模型中得到了解决,当然,在 IDEF1X 或关系数据库中,这也不是限制。但现在,在逻辑上,它干扰了你的学习和进步。

  • 在 BandItem 中,我们希望 PK 是(BandItemId,BandId)。但 ERwin 不允许这样做,因为它说“子类型 PK 必须是超类型 PK 而且不能有其他东西”。实际上,只要超类型 PK 是主导标识符,另一个标识关系是可以接受的。为了解决这个问题:

  • 删除子类型符号

  • 创建两个标识关系 Item::FloorItem 和 Item::BandItem。

  • 我们不得不使非标识的关系现在可以变为标识关系。

  • ERwin 现在将迁移的 PK 解决为 FK,而不会有重复。

  • 是的,请把角色放回去。

U.9) 现在我明白你试图在 Review 集群中做什么了,因此,首先,让我说一下,你对其进行了正确建模,一直到 Rating。

  • 但是在 Review 本身存在一个基本问题。使用 ReviewerId 作为 PK,每个评论者将只允许一个评论。当然,你想要每个评论者针对每个乐队/乐队项目进行一个评论,但这在子类型中被隐藏得更深。基本上,在这里使用超类型-子类型过于受限制。早期理解很好,但现在我们需要超越它。
  • 不要使用 Review 集群,而是创建两个 Review 表,一个 BandReview 和一个 ItemReview。
  • 关系将是 Person::BandReview 和 Band::BandReview,以及 Person::ItemReview 和 BandItem::ItemReview。
  • 然后,每个表都将拥有子项 %Rating、%Comment 和 %CommentRating。

M.13) Order::OrderShipAddress 为 1::0-1,正确。
PartyAddress::Order 为 1::0-n,正确
因此,Shipping Address 应该是 PartyAddress::OrderShipAddress 1::0-n

M.14) 目前的付款方式只允许每个订单进行一次支付,这可能是您需要的,但关系是1::1-n。如果您需要更多,请将SequenceNo添加到PK中。

M.15) 类型很好。但是子类型需要在PK中添加一些内容以允许多种类型。我现在会将Genre.Name更改为Genre.Genre,并将SubGenre添加到SubGenre PK中。

  • 这将修复Event.GenreId。

M.16) 场馆现在需要一个名称作为PK。如果您准备好更好的密钥,则ShortName和Name作为属性下移。

Q.4) 确认。由于我们在Order中有一个识别关系和PK(PartyId,OrderNo),因此OrderNo是PartyId内的顺序号,对吗?

使用V1.5。包括一些属性。最好的方法是启动函数模型(现在同时处理数据模型)或至少处理所有屏幕的所有功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接