希望找出对以下要求进行建模的正确方法。
- 有 3 种类型的“派对”需要关注,粉丝、乐队和乐队成员。
- 该乐队成员将始终与乐队相关联,也可以是任何乐队的粉丝。
- Fan、Band和BandMember之间有共同的属性,但这三者中的每一个也会有自己独特的属性。
- 一个粉丝可以是任何乐队的粉丝,也可以完全没有
这是一个更大想法的一小部分,但它在扩展模型时造成了混乱。我相信它必须是图表 2 或其他选项,因为我看不到 BandMember 如何与第一个模型中的 Band 关联。
我很感激任何意见。
希望找出对以下要求进行建模的正确方法。
这是一个更大想法的一小部分,但它在扩展模型时造成了混乱。我相信它必须是图表 2 或其他选项,因为我看不到 BandMember 如何与第一个模型中的 Band 关联。
我很感激任何意见。
首先是一些关于理解限制的警告。所有正在使用或存储的数据都需要一起考虑/建模。例如。无论如何,您已经在“在扩展模型时造成混乱”中发现了这一点。从我的角度来看,不知道Parties
(子类型)如何与其他实体相关,这限制了我提供完全正确的答案(不会改变)。
由于您分两批提供数据,因此答案将分两批提供,第二批将需要对第一个模型进行更改。不是抱怨,只是事先建议您,因为如果我预先看到所有数据,就可以避免这种情况。
非常感谢您需要 (a) 对数据建模和 (b) 通过概念、逻辑和物理的科学(记录了 30 多年)。这正是我所做的。您无法想象正式流程所节省的时间和精力。
必须提到的是,关系建模是行业巨头 EF Codd 博士和 R Brown 在 1980 年代的工作。该方法是基于他们的工作。IDEF1X 于 1993 年成为 NIST 标准。当我回答数据建模问题时,我并没有提供我写过一本书的个人方法,而是站在巨人的肩膀上。
我坚持 EF Codd 博士的关系模型。
我拒绝伊达的作品;达尔文;费金;等等,因为它与关系模型相矛盾,所以它是反关系的。
相比之下,ERD (P Chen) 是前关系、前 IDEF1X 和原始的。它没有标识符的概念,它不能处理关系键。令人震惊的是,ERD 仍然被教授为“关系”,并且 IDEF1X 被压制。30 年。
另外,即使实现了子类型,它们也以非常有限的方式实现。子类型具有改变超类型角色的效果。正确的实现确实非常罕见,我在任何地方都没有看到过(当然除了我自己的客户数据库实现和一些高端供应商)。
关键是,这可能看起来“复杂”,但实际上并非如此,它实际上非常简单。
这就是 Ken Downs 和 Chris Behrens 将建模的简单性(高度可扩展)与未建模的实现(不正确且不可扩展)混淆的地方,这是由于 Martin Fowler 等矮人所建议的简单化方法。没有冒犯,我知道人们会依附于他们所知道的并将捍卫他们所知道的,尽管这可能是有限的。
请注意,每个子类型本身也是一个完全有效的实体(物理中的表,当我们到达那个阶段时),并且可以独立存在。
对于与这些子类型有关系的较低级别或事务或功能表,诀窍是使用正确的子类型(角色)。常见的错误是他们使用Party
,然后是 Subtype 或 Role 的含义,正确的参照完整性就丢失了。
单独地,所有 RoleNames 都派生自Party
,但这不是使用Party
正确 Role 的正当理由。
在这里,您非常了解数据,但是(没有人教过您,并且)您混淆了角色和子类型。
BandMember
并且Fan
不是Parties
。它们是Persons
, first (并且Person
是Party
, second)
为了清楚地说明这些点,在这个概念级别,我们需要使用实体和标识符(而不是属性),而不仅仅是实体。因此,我也提供了这一点。
我在介绍模型之前指出了这些,因为您似乎对学习 IDEF1X(用于建模关系数据库的标准方法)非常感兴趣,以期在将来简化您的模型。SO 或任何网站都不是正规互动教育的好媒介,但我们会尽力而为。
在模型(1)中,Band
不能是独立的(方角):因为它被识别为依赖于Party
;它是 的子类型Party
;并且它具有相同的标识符。
缺失的基数至关重要。将其放入实际上将有助于解析模型。我对 IDEF1X(圆圈)与 IEEE(鱼尾纹)并不大惊小怪,但我总是边走边把它们放进去,并随着模型的进展不断改变它们。
Band
是由one-to-many Members
组成的。等等。在这个阶段,规则也很重要。建模实际上就是对规则建模。因此,更正或修改规则是建模过程的一部分。
一个粉丝可以是任何乐队的粉丝,或者根本没有是不合理的。如果 aPerson
根本没有,那么他们就是普通大众的一员,并且他们与 any 没有任何关系Band
。一个普通的Person
。
AFan
与至少一个 有关系Band
。事实上,与 a 建立关系Band
就是将 a 带Person
出该领域并导致存储Fan
详细信息或特定粉丝详细信息的原因。
如果有这样的实体Fan with no Band
(即,您正在存储它的详细信息,Fan
根据我的模型分开),请告知,我会更改模型(纸很便宜!)。
动词短语在这个阶段也很重要;不亚于我上面关于规则和基数的观点,它是建模过程的一部分,随着模型的进展它需要改变/调制。你不会相信正确使用动词短语是多么重要。将它们放入其中可能有助于您澄清子类型与角色。这是每个数据建模师都熟记的定义。
实体是模型中的名词
关系是动词,名词之间发生的动作
动词短语定义了这些动作(这就是为什么它们被准确地称为动词短语,这不是一个有趣的名字)。
如IDEF1X Notation文档中所述,对于关联表,将动词短语“通过”它们读取到关联另一端的父级。
APerson
使一对多Bands
,因此是Member
ABand
由一对多People
组成,它们是Members
APerson
光顾 a Band
,这使他们成为 a Fan
(不仅仅是一个在表格Person
中有一行的人)Fan
ABand
取决于People
, 谁是Fans
想出最短、最有意义的动词短语;不使用简单的词(要避免“包含”),对建模者来说是一个挑战。随意改进我提供的动词短语。
这是IDEF1X 中实体和键级别的派对数据模型。
不熟悉关系数据库建模标准的读者可能会发现我的IDEF1X 表示法很有用。
我所做的只是解决子类型;角色;如上所述的关系的基数。
当您评估您的第二批或您的交易实体时,子类型与角色的相关性对您来说会更加清晰(正如您所说,这里我们只有识别实体)。
标识符。这是值得一提的,不仅是为了阐明模型,还因为它是使用 IDEF1X 标识符以及它们部署的功能的一个很好的例子。您已经在您的模型中表明您理解(实线),我只是对其进行全面处理。
Person
并且Band
是 的子类型Party
。它们也是 的角色Party
。因此,我们从那一点向下使用PersonId
and ,而不是(即使它是)。BandId
PartyId
PartyId
当 aPerson
扮演 的角色时Member
,我们使用MemberId
(which is PersonId
, which is PartyId
)。
当 aPerson
扮演 的角色时Fan
,我们使用FanId
(which is PersonId
, which is PartyId
)。
假设您列出的Fans
是 a Band
,您的查询以 为中心Fan
。如果您Id
在每张桌子上都有这些代理键,您将被迫加入Person
,然后加入Party
。但是使用您拥有的关系标识符,您可以直接转到Party
:
SELECT ...,
Name -- Party.Name
...
FROM Party
JOIN Fan
ON PartyId = FanId
并跳过Band
中间的表格。是的,事实是,规范化关系数据库需要更少的连接、更少的资源(处理、缓存、磁盘 I/O),这也是它们性能如此出色的原因之一。神话没有科学依据。
请评估并提出具体问题。
有关子类型的一般处理以及真正 SQL 平台的实现细节,请参阅我的子类型文档。
我认为这比你想象的要简单。您有两个对象 - Band 和 Person,它们可以以两种不同的方式连接起来,既可以作为粉丝,也可以作为成员。这是一个没有外键或任何东西的快速数据库脚本:
CREATE TABLE [dbo].[XREFBandMembers](
[MemberID] [int] NOT NULL,
[BandId] [int] NOT NULL,
CONSTRAINT [PK_XREFBandMembers] PRIMARY KEY CLUSTERED
(
[MemberID] ASC,
[BandId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[XREFBandFans](
[FanId] [int] NOT NULL,
[BandId] [int] NOT NULL,
CONSTRAINT [PK_XREFBandFans] PRIMARY KEY CLUSTERED
(
[FanId] ASC,
[BandId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[People](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](100) NOT NULL,
CONSTRAINT [PK_People] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[Bands](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Bands] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
至于关系特定属性,您可以将它们放在 XREF 表中,例如,FanClubMembershipNumber 放在 XREFBandFans 中。