在尝试学习数据存储艺术的过程中,我一直在尝试获取尽可能多的可靠信息。 PerformanceDBA 在以下帖子中发布了一些非常有用的教程/示例:我的数据标准化了吗? and 关系表命名约定。我已经问过这个模型的一个子集问题here.
因此,为了确保我理解他提出的概念以及我在其他地方看到的概念,我想再前进一两步,看看我是否掌握了这些概念。这就是这篇文章的目的,希望其他人也能从中学习。我所呈现的一切对我来说都是概念性的,是为了学习而不是在某些生产系统中应用它。从 PerformanceDBA 那里获得一些意见会很酷,因为我使用了他的模型来开始,但我感谢任何人提供的所有意见。
由于我对数据库,尤其是建模很陌生,我将第一个承认,由于缺乏该主题的专业知识,我可能并不总是提出正确的问题,清楚地解释我的想法,或使用正确的措辞。因此,请记住这一点,如果我偏离了轨道,请随时引导我走向正确的方向。
如果对此有足够的兴趣,我想从逻辑阶段到物理阶段来展示该过程的演变,并在 Stack 上分享。不过,我将保留逻辑图的这条线索,并为附加步骤开始新的线索。根据我的理解,我最终将构建一个 MySQL 数据库来运行一些测试,看看我的想法是否真正有效。
以下是我想要在此概念模型中捕获的内容的列表。编辑V1.2
就这样,也许有点复杂,但随着流程的发展和社区的投入,对于许多人来说可能是一个很好的学习工具。有什么意见吗?
编辑v1.1回应 PerformanceDBA
U.3) 这意味着数据库中没有除 Band 商品以外的商品。正确的 ?这是我最初的想法,但你让我开始思考。也许该网站想要出售自己的商品,甚至是乐队的其他商品。不确定为此制作一个模组。是否需要对目录部分进行整个重新设计,或者仅需要重新设计与乐队之间存在的识别关系? 尝试制作一个模组来销售完整的专辑或歌曲。无论哪种方式,它们都是电子格式,仅供下载。这就是为什么我将专辑列为由歌曲组成而不是两个单独的实体。
U.5)我理解你提到的与Favorite 的循环关系。我想讨论“它是一个具有某种形式的分化(FavoriteType)的实体,它可以识别其处理方式”,但我不清楚如何做到这一点。我在这里缺少什么?
u.6)“业务规则这可能是你唯一薄弱的领域。”
感谢您的诚实回复。我将重新解决这些问题,但我希望首先通过我发回给您的回复来消除我头脑中的一些困惑。
Q.1)是的,我希望接受、拒绝和阻止。我不确定您指的是这将如何改变逻辑模型?
Q.2)一个人不一定是用户。他们只能作为乐队成员而存在。这就是你问的吗?
小问题
零、一或更多……哎呀,我承认我在构建模型时忘记了这一点。我按原样提交此版本,并将在未来版本中解决。我需要阅读更多有关约束检查的内容,以确保我理解事情。
M.4)取决于您是否设想将来使用 OrderPurchase。 您能详细解释一下您在这里的意思吗?
编辑V1.2响应 PerformanceDBA 的输入...
得到教训。
U.2)在此模型的概念中,仅需要跟踪场地作为事件的位置。无需收集更多数据。话虽这么说,活动将在给定的活动日期举行,并将在场地举办。场地将举办多个活动,并且可能在给定日期举办多个活动。在我的新模型中,我的想法是 EventDate 已经与 Event 绑定在一起。因此,Venue 不需要与 EventDate 建立关系。不过,您在 U.2 下列出的第 5 个和第 6 个项目符号让我质疑我的想法。我在这里错过了什么吗?
U.3)是时候将 Item 和 Band 之间的链接移至 Item 和 Party 了吗?根据目前的设计,我认为不可能销售与您提出的乐队无关的商品。
U.5)我根据您的输入离开,而不是使其成为离散的超类型/子类型关系,因为我没有看到这种类型的汇总有什么好处。
附加修订
AR.1) After going through the exercise for FavoriteItem, I feel that Item to Review requires a many-to-many relationship so that is indicated. Necessary?
好的,我们开始 v1.3
我花了几天时间研究这个版本,反复修改我的设计。一旦逻辑过程完成,因为我想看看我是否走在正确的轨道上,我将深入了解我所学到的知识以及作为初学者在经历这个过程时遇到的麻烦。这个版本的重点是它需要添加一些键来帮助我了解我过去缺少的内容。事实证明,完成制作矩阵的过程也有很大帮助。无论如何,如果没有 PerformanceDBA 提供的输入,我仍然会是一个在黑暗中迷失的灵魂。谁知道我现在的设计可能会再次证明我仍然是这样,但我学到了很多东西,所以我知道我手里至少有一个手电筒。
此时此刻,我承认我仍然对识别和非识别关系感到困惑。在我的模型中,我必须使用非空值的非标识关系来加入我想要建模的关系。在阅读了有关该主题的大量内容后,似乎在该主题上存在很多分歧和优柔寡断,因此我做了我认为在我的模型中代表正确事物的事情。何时强制(认同),何时自由(非认同)?有人有意见吗?
编辑V1.4
好的,接受了 V1.3 输入并清理了 V1.4 的内容
目前正在开发 V1.5 以包含属性。
编辑V1.6
好吧,我在这里发帖已经有一段时间了,但这个项目的工作仍在进行中。我现在发布 V1.6,其中包含与上次发布 V1.4 相比的一些更改。该版本展示了 Keys 的进一步发展。它仍然不包括属性或任何 AK 或 IE。我已经开始研究物理模型,并使用它来帮助处理属性,并尝试阐明我在定义 AK 和 IE 时遇到的问题。逻辑模型的下一篇文章将包括这些键和属性。
Method
我将介绍具体细节,但我将完全介绍一两个主题领域,而不是全部。您可以选择它并将其应用到所有主题领域。
我还没有对核心主题领域做出回应,因为我们仍在处理识别实体问题。当这个问题解决后Reviews
等会更容易;交易实体依赖于识别实体。
方向
D.1) 我知道我说过我需要查看整个模型。有一个例外。历史数据、临时数据或审核数据(例如编辑和存储的版本)。在这个早期阶段,它们可以被搁置;在逻辑模型完成之前实施。这是因为(a)它们是某个父项的简单依赖项(b)需要首先根据所有其他表对父项进行建模,以及(c)排除不必要的复杂性,从而使我们能够专注于相关的场地。
Has/Had
)。现在请使用现在时,因为重点是建模,而不是归档。未解决
U.1) 可选父项
这是完全不允许的。不仅仅是 IDEF1X,而是任何诚信概念。如果定义了 FK Reference,则必须有一个 Parent。为了允许可选的父项,必须删除(或不实施)FK 参考。根据定义,这样的条件将排除结果作为“关系数据库”的资格。例如。Address:Order
.
Order
必须有一个Address
出于法律或税务原因;这与标准要求问题是分开的。U.2) 事件
Party::PartyAddress
是正确的;Address::PartyAdress
是正确的。Event::Address
需要工作。地址是一个识别参考表;如果使用的话,它将是父级,Event
将是孩子。我把它留给你来识别/建模多个Events
到一个位置,并且Events
在一个或多个地点。
可能涉及一个场地。或者一个EventOccurrence
但如果是通用的Event
这发生在多个位置,不需要实体,Address
已经在Order
.
U.3) 假设Catalog
是传统意义上的条目(JCPenney 2011),即待售或出租物品的列表。
OrderSaleItem
是正确的
临界点。Catalog
是依赖的,并且只能存在于Band
,作为资产。美好的。这意味着数据库中没有除 Band 商品以外的任何商品。正确的 ?
我可以看出“与布鲁斯兄弟的晚间表演”是如何Event
可以订购、开具发票和付款。还评论、评论等。
我看不出如何Song
符合这一点。乐队出售专辑、歌曲还是两者兼而有之?
有没有其他乐队商品:音乐会/活动纪念品;海报;雕刻小眼镜?
与您引用的命名约定以及数据库的其余部分一致,Catalog
(内容)应命名Item
(行)。你已经(当然?)使用过它OrderSaleItem
,( 与OrderSaleCatalog
.
U.4) 流派
没问题an Item is classified by one-to-many Genres
.
我认为另外a Genre classifies one-to-many Items
。关系是一对多的(当我们到达物理时,它将被解析为关联表)。
U.5) 最喜欢的
的基数Item::Favorite
是相反的。当您更正该问题时,Favorite
主题领域将需要进一步建模。
同一对实体之间的循环关系或双路径是未解析模型的信号。一般来说,一个是正确的,另一个是多余的。 (也有例外,但这里没有;当这种情况发生时,动词短语会区分它们。)
Either Band::Favorite
xor Item::Favorite
是正确的,但不是两者都正确。
Item::Favorite
似乎是正确的,因为Band
已经被识别在Item
同样,一Favorite
乐队实体and商品听起来不扎实。单个中的每个标识符Favorite
实体是一个Party
。当我们标准化时它会崩溃,不妨要求在这个阶段澄清标识符。它是具有某种形式差异化的一个实体(FavoriteType
) 指明其处理方式;或一个Favorite
对于乐队,另一个对于商品,在这种情况下不需要区分,从而消除了歧义。
U.6) 业务规则 这可能是您唯一薄弱的领域。一般反应。您已经单独完成了这些任务(所有建模与编写 BR)。这些与型号不匹配。当您经历下一个周期时,以业务规则为指令,同时对它们进行调整,就像实体、关系和动词短语一样。
Question
Q.1) 用户/朋友
你完美地掌握了它的本质。以及关系的基数。 (对此进行全面处理。)这对于“已接受”是正确的Friend
.
因此时态应该是过去时(与大多数行一致)
Requested
,以及待定的Accepted
,属于少数。轻松实现IsAccepted
位或布尔值。
稍后你可能有IsRejected
or IsBlocked
(后者应该是一个单独的实体)。
这是你所需要的吗?
Q.2) 的依据是什么?Person is zero-to-many Users
?
小问题
M.1) 仅单数。
M.2) Party Has zero-to-many Addresses
。我认为他们必须有一个,才能进行业务(但也许不是对所有人)Users
).
M.3) Order May Have zero-to-many Payments
。 “要求”意味着首先Payment
必须同时插入Order
.
M.4) OrderSaleItem
应该OrderItem
xor Order
应该OrderSale
。取决于你是否设想OrderPurchase
将来。
主题领域示例
不熟悉关系数据库建模标准的读者可能会发现IDEF1X 表示法 useful.
如前所述,我不提供完整的数据模型,仅提供指导。这只是其中之一进展一个选定的主题领域。它在任何方面都不“正确”或完整。
你的动词短语非常好。我已经提供了替代方案供您考虑,它们不是“正确”或“更好”。您需要选择他们或您自己的进度。目标是在每种情况下获得最简洁、最准确的 VP。
没有建议Person
是正确的并且User
不正确,等待您的回答。但我必须在模型中使用一些东西;由于您已将它们建模为单独的,因此评估对位可能会很有趣。
因此,继续推进模型,然后再次发布(只需编辑问题,保留标题段落,然后替换其余部分)。
这当然是一个进步。
我已经以伪合法格式重新对项目进行了编号,包括章节标题,以便我们可以在整个过程中保留编号,并不断添加内容。事实上,它也确实缓解了 SO 编辑问题。
U.3) 是否需要对目录部分进行整个重新设计,或者仅需要重新设计与乐队之间存在的识别关系?
不。这是在这个级别工作的伟大之处,您在这里做出的决定将是数据运行的铁轨,作为货运,或不运行(因此需要替代运输和重型起重来导出,在大量代码或代码的形式额外的数据仓库)。而且这里的决策成本很低(建模时间、论文)。
现在,项目仅存在于乐队的上下文中。它是依赖的。为了允许非乐队商品,它需要是独立的。然后现有的超/子类型集群需要重新设计。
尝试制作一个模组来销售完整的专辑或歌曲。无论哪种方式,它们都是电子格式,仅供下载。这就是为什么我将专辑列为由歌曲组成的原因
而不是两个独立的实体。
不确定你的意思(你have两个独立的实体)。
看来你还没有看到我的主题领域示例. Note如果你现在打开它,它包含我拥有的部分添加了V1.1;我有没有改变昨天有什么,V1.0 响应。
实际上,这意味着您应该在查看示例时再次浏览我的 V1.0 答案。
U.5) ...但我不清楚如何做。我在这里缺少什么?
具有差异化的实体的一个示例是您拥有的任何超类型/子类型集群。 The favorite 是超类型,BandFavourite 和 ItemFavourite 是子类型;允许每个分别引用 Band xor Item。
您已经对 ItemFavourite 进行了建模。现在的问题是,ItemFavourite 的事实是否意味着该 Band 是 Favourite?或者 BandFavourite 是一个离散的事实?在示例中,我对后者进行了建模,没有 Favourite::ItemFavourite/BandFavourite 结构。
Q.1) 是的,我希望接受、拒绝和阻止。我不确定您指的是这将如何改变逻辑模型?
V1.0 没有变化(我已经说过它非常完整),但您可能需要一个额外的实体。
在 Friend 中您需要三个位或布尔指示器。这将为这些状态提供服务:
Requested
(但不被接受)
Requested & Accepted
.
但被阻止的人不是朋友(或者以前可能是朋友,但自从被阻止后就不再是朋友)。因此,要么必须更改实体名称以反映这一点(两个关系无需更改),要么 Blocked 必须是一个单独的实体。第二个关系的两个不同含义导致复杂性,因此我会选择后者。
对于前者,我们还有其他状态:
Blocked
Q.2) 一个人不一定是用户。他们只能作为乐队成员而存在。这就是你问的吗?
不,为什么我们需要区分 Person 和 User ?单独的操作或属性是什么?到目前为止,我将 Person 和 User 视为同一个实体;人员是没有活动的用户。
这是最后一项,阻碍我们处理核心主题领域。
M.3) 我需要阅读更多有关约束检查的内容,以确保我理解事情。
M.4) 取决于您是否设想将来使用 OrderPurchase。您能详细解释一下您在这里的意思吗?
在模型的背景下。您提供用于制作(项目)销售订单的结构。因此,Item、Order 和 OrderItem。
但是,如果您还提供了跟踪采购订单的结构(购买物品以及办公用品、租金等),那么您需要区分销售订单和采购订单。所以:
Item
订单销售和订单销售项目
订单购买和订单购买项目
1.1版
U.2) 事件进展
EventDate 看起来不错。我将关系定义为Event Was Perfromed On EvenDate
.
虽然 ItemGenre 很完美,但 Event::Venue 需要改进。这是你一贯犯的错误,因此需要解释。
你已经建模了Venue
正确的是,它是独立的并且确实存在于上下文之外Event
. But Event May Be [Held] At zero-to-many [Independent] Venues
不可能。
活动在许多场馆举行,而场馆也举办许多活动。如果仅此而已,由于这是逻辑级别,因此您可以绘制多对多关系,然后就完成了。在物理层面,该关系是通过实现关联表来解决的,其中的PK是两个父PK,并且没有数据。 (敌人就是一个很好的例子。)
但是,如果有数据(例如,您需要跟踪参加者的日期或数量或其他内容),那么它就不是关联表,而是另一个实体。发生在活动和场地之间的事情。
EventDate 是一个很好的候选者。我们已经有了那个和日期。只需添加场地并搅拌即可。我将在活动和场地之间发生的事情称为表演。
同样,EventAddress 已取得进展,但尚未完成。
活动有地址或场地有地址吗? (建模,无需言语)
如果地点:您是否需要该地点的所有历史地址(如派对),还是只需要当前地址(如订单)?
M.5) 子流派。你能解释一下为什么子流派是(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
.
巨大的进步。
U.2) 事件进一步进展
根据您的编辑以及新的要求,有些是,有些不是。数据模型的所有其他主题领域都非常完整(对于逻辑),这一领域很混乱,几乎没有得到解决。部分是因为增加了要求(没有抱怨,这在现实生活中发生;这取决于你如何处理它)。
我在这里要强调的要点是,数据模型应该始终对现实世界进行建模,而不仅仅是业务需求。 (a) 使 DM 免受变更的影响,(b) 为添加的需求提供坚实的平台。这并不意味着您必须对整个现实世界进行建模,但是您建模的部分必须反映现实,而不是被压缩以满足需求。
其次,活动、乐队活动、表演等之间的区别缺乏明确性。现在,活动是派对-乐队-项目-活动。这很好,但它不适用于新样式的“按要求事件”。
第三,你对派对地址和秩序有很好的把握,但对场地却把握不好。
由于您接受符合标准的模型并因此进行处理,因此地址是一个参考表。
它是独立的(方角)
实际上,您可以将地址及其上方的所有内容放在第一页上;使模型的这一部分成为第二页,并且仅在此页上有地址。
正确建模:一方有地址历史。他们必须至少拥有一项当前的 { IsBilling |正在运送 | IsPhysical } 地址,基于正在执行的任何活动。
正确建模:一个订单有一个 IsBilling Address(如果您需要 IsShipping,则需要添加一个单独的关系)。
地址不是地点的子项(也是独立的,正确的)。我不认为场地位于零到多个地址中。 (也许这是旧的基数反转错误,但我不确定,因为事件和地点的其他混乱。)
实际上 Address::Order 是可疑的。 (Q.3) 您是否希望订单提及任何有效地址,或执行订单方的具体地址?
返回活动。接受声明的 EventDate。这很好,但评论等适用于一般音乐会,而不是他们在蘑菇上表演的单一音乐会。 转到 V1.3。
您的术语“事件”等与要求等一致,但不支持所述要求。
因此,让我们开始按照现实世界中使用“事件”的方式来使用“事件”,并以这种方式对其进行建模。我们所说的“活动”,即派对乐队项目,实际上是一种表演。而且不是预定的通用活动,而是在特定地点举行的单一活动。
这要么就是您对 EventDate 的含义,要么 EventDate 解析为 Performance。
如果你不介意的话,我就不打一千字了,给你一张图。主题领域示例 V1.2
请注意,每个事件的多个频段已解决。
动词短语直接来自天堂。一个地址主办了多个场馆,每个场馆举办多个活动,每个场馆都有多个表演,每个场馆都是一个派对乐队项目。
U.3) 是时候将 Item 和 Band 之间的链接移至 Item 和 Party 了吗?根据目前的设计,我认为不可能销售与您提出的乐队无关的商品。
首先,我们需要使用关系术语,不是因为我是学究,而是因为真正的大师说它确实有助于过渡到关系世界。
其次,我们不能通过“移动关系”来实现这一点。
你必须对非乐队商品进行建模:你将如何销售它;追踪它;为此获得报酬。无论你想要评论和回复等。我不明白派对与它有什么关系,现在我们正在销售乐队物品,而不是派对物品。考虑引用完整性问题。
1.2版
AR.1) 在完成“FavoriteItem”的练习后,我觉得要审核的“Item”需要多对多的关系,因此需要指出这一点。必要的?
在V1.1中,一个Item有很多Reviews,一个Review是关于一个Item的。一个人生成了许多评论(每个项目一个)。这是合乎逻辑的。
A Review is about many Items
不合理。
如果有的话,现在 FavouriteItem/FavouriteBand 已经解决了,Review 也需要同样的解决和区分:我们是否需要区分 BandReview 和 ItemReview?好/坏的 ItemReview 是否表明好/坏的 BandReview 或者它们是离散的?
评论(就目前而言)不能是关于either a Band or一个物品。这意味着两个外键,其中之一将为 Null,并且不允许使用 Null FK。 Item和Band已经分化,而且分化已经成熟。
ItemReviews 可以进行总结等,但这是一个不同的故事。
U.7) 这给我们留下了一个需要解决的新问题。如果评论可以是关于乐队、专辑、歌曲或表演,我们如何确保引用完整性。我们不需要 AlbumReview 来引用 SongReview 等。对其进行建模。
R.5) 该模型当前在项目级别提供流派,这意味着专辑和歌曲(可以通过 CHECK 约束禁止商品)。不是乐队。这可能就足够了,因为 (a) 乐队随着时间的推移而变化,(b) 项目级别的分类更加精确,(c) 乐队流派可以轻松地从他们的专辑或歌曲中得出。
如果您需要单独的乐队流派,则需要添加它。
事件类型怎么样?如果您需要它,我认为每个活动都会有一种类型。
请记住,像场地和流派这样的表是主要数据库中严格的搜索条件。用于分析的向量。
数据仓库男孩需要add这在作为方面他们的事实;在正确建模的数据库中,它们已经作为事实的维度存在。显示所有安排举办吸引超过 10,000 人的“民间音乐”活动的场地太容易了。
.
讨论点。并不是说上面的说法是错误的。我在数据库和 iTunes 中发现的是,精度很重要。当你可以拥有类型::特定的东西时,为什么还要自由放任类型::几件事。如果您只有 Genre::Song,并且 Song 只有一种 Genre,那么专辑和乐队就是精确的汇总。我们现在的方式,取决于数据录入人员的音乐知识,而且Genre::东西很多,所以比较松散。流派::歌曲很紧凑。
R.6) 会员可以证明他们将参加活动没有建模。还要澄清兴趣、预订和出席率。
R.8) 未建模。
M.3) 问题已结束,但动词短语保持不变。
M.7) 逻辑模型与关联表。现在该问题已解决,请删除逻辑模型的所有关联表;任何剩余的表(两个父级之间)都将包含数据。这意味着,遍历所有从属表并删除任何没有数据的表。因此,V1.3 应该不会那么混乱。
M.8) 项目is订单项目。
M.9) 现在“当事人-个人-用户”问题已经解决。独占子类型结构需要鉴别器,并且约束将用于强制完整性。如果有很多,PartyType 就是最佳选择。但对于两个人来说,一列IsBand
or IsPerson
就足够了。
M.10)您已经纠正了基数反转的错误,但一些动词短语仍然走错方向。
实际上,我认为如果我们进入逻辑键/属性级别(而不仅仅是实体关系级别),很多这些问题会更清楚。现在是我们这样做的时候了。例如:
Q.3) 订单:地址可疑。该约束不太正确,因为这将允许订单any地址,而不是执行命令方特定的地址。
但由于你是 MySQL,它没有引用完整性,你可能不知道它在实际 SQL 中是如何完成的,所以我将提供 FK 定义,它恰好也是 RI 约束。当你没有 SQL 的时候,指望你理解我的简洁语句是不公平的,这些语句基于 RM、规范化并由 SQL 支持。
Order.PartyId
),仅允许属于 PartyId 的 PartyAddress 子集。地址资格示例
继续第二部分...