5

希望找出对以下要求进行建模的正确方法。

  1. 有 3 种类型的“派对”需要关注,粉丝、乐队和乐队成员。
  2. 该乐队成员将始终与乐队相关联,也可以是任何乐队的粉丝。
  3. Fan、Band和BandMember之间有共同的属性,但这三者中的每一个也会有自己独特的属性。
  4. 一个粉丝可以是任何乐队的粉丝,也可以完全没有

这是一个更大想法的一小部分,但它在扩展模型时造成了混乱。我相信它必须是图表 2 或其他选项,因为我看不到 BandMember 如何与第一个模型中的 Band 关联。

我很感激任何意见。

替代文字

替代文字

4

2 回答 2

12

警告

  1. 首先是一些关于理解限制的警告。所有正在使用或存储的数据都需要一起考虑/建模。例如。无论如何,您已经在“在扩展模型时造成混乱”中发现了这一点。从我的角度来看,不知道Parties(子类型)如何与其他实体相关,这限制了我提供完全正确的答案(不会改变)。

    由于您分两批提供数据,因此答案将分两批提供,第二批将需要对第一个模型进行更改。不是抱怨,只是事先建议您,因为如果我预先看到所有数据,就可以避免这种情况。

  2. 非常感谢您需要 (a) 对数据建模和 (b) 通过概念、逻辑和物理的科学(记录了 30 多年)。这正是我所做的。您无法想象正式流程所节省的时间和精力。

    • 但是,这并没有出现在我在 SO 的回答中,因为它是一个“问答”网站,我必须在提问者的层面上回答。(我比其他人更全面地回答问题,即便如此,也会引起负面评论!)。请放心,我会通过正式的顺序。
  3. 必须提到的是,关系建模是行业巨头 EF Codd 博士和 R Brown 在 1980 年代的工作。该方法是基于他们的工作。IDEF1X 于 1993 年成为 NIST 标准。当我回答数据建模问题时,我并没有提供我写过一本书的个人方法,而是站在巨人的肩膀上。

    • 我坚持 EF Codd 博士的关系模型

    • 我拒绝伊达的作品;达尔文;费金;等等,因为它与关系模型相矛盾,所以它是反关系的。

    • 相比之下,ERD (P Chen) 是前关系、前 IDEF1X 和原始的。它没有标识符的概念,它不能处理关系键。令人震惊的是,ERD 仍然被教授为“关系”,并且 IDEF1X 被压制。30 年。

数据建模

  1. 是的,超类型-子类型结构在这里是正确的。不幸的是,它并不常见,因此不被普遍理解。
  • 子类型早在关系模型之前就已经存在,并且继续存在。IDEF1X 是唯一的关系数据建模标准,它具有特定的符号。ERD 什么都没有。
  1. 另外,即使实现了子类型,它们也以非常有限的方式实现。子类型具有改变超类型角色的效果。正确的实现确实非常罕见,我在任何地方都没有看到过(当然除了我自己的客户数据库实现和一些高端供应商)。

  2. 关键是,这可能看起来“复杂”,但实际上并非如此,它实际上非常简单。

    这就是 Ken Downs 和 Chris Behrens 将建模的简单性(高度可扩展)与未建模的实现(不正确且不可扩展)混淆的地方,这是由于 Martin Fowler 等矮人所建议的简单化方法。没有冒犯,我知道人们会依附于他们所知道的并将捍卫他们所知道的,尽管这可能是有限的。

    • 请注意,每个子类型本身也是一个完全有效的实体(物理中的表,当我们到达那个阶段时),并且可以独立存在。

    • 对于与这些子类型有关系的较低级别或事务或功能表,诀窍是使用正确的子类型(角色)。常见的错误是他们使用Party,然后是 Subtype 或 Role 的含义,正确的参照完整性就丢失了。

    • 单独地,所有 RoleNames 都派生Party,但这不是使用Party正确 Role 的正当理由。

    • 在这里,您非常了解数据,但是(没有人教过您,并且)您混淆了角色和子类型。

    • BandMember并且Fan不是Parties。它们是Persons, first (并且PersonParty, second)

  3. 为了清楚地说明这些点,在这个概念级别,我们需要使用实体和标识符(而不是属性),而不仅仅是实体。因此,我也提供了这一点。

    • 看来您拥有 ERwin(最好的!);它使您可以非常方便地查看该级别的单个模型。即使在这个抽象级别,也要在实体中实现标识符。

障碍

我在介绍模型之前指出了这些,因为您似乎对学习 IDEF1X(用于建模关系数据库的标准方法)非常感兴趣,以期在将来简化您的模型。SO 或任何网站都不是正规互动教育的好媒介,但我们会尽力而为。

  1. 在模型(1)中,Band不能是独立的(方角):因为它被识别为依赖于Party;它是 的子类型Party;并且它具有相同的标识符。

  2. 缺失的基数至关重要。将其放入实际上将有助于解析模型。我对 IDEF1X(圆圈)与 IEEE(鱼尾纹)并不大惊小怪,但我总是边走边把它们放进去,并随着模型的进展不断改变它们。

    • 您的模型没有显示 aBand是由one-to-many Members组成的。等等。
      .
      虽然编程可以逐步进行(一旦定义稳定),建模则不行。例如。你不能为实体建模,但不能为关系建模;关系但不是基数。这就是为什么它们是不同的科学,程序员不会成为好的建模者,反之亦然。
      .
  3. 在这个阶段,规则也很重要。建模实际上就是对规则建模。因此,更正或修改规则是建模过程的一部分。

    • 一个粉丝可以是任何乐队的粉丝,或者根本没有是不合理的。如果 aPerson根本没有,那么他们就是普通大众的一员,并且他们与 any 没有任何关系Band。一个普通的Person

    • AFan与至少一个 有关系Band。事实上,与 a 建立关系Band就是将 a 带Person出该领域并导致存储Fan详细信息或特定粉丝详细信息的原因。

    • 如果有这样的实体Fan with no Band(即,您正在存储它的详细信息,Fan根据我的模型分开),请告知,我会更改模型(纸很便宜!)。

  4. 动词短语在这个阶段也很重要;不亚于我上面关于规则和基数的观点,它是建模过程的一部分,随着模型的进展它需要改变/调制。你不会相信正确使用动词短语是多么重要。将它们放入其中可能有助于您澄清子类型与角色。这是每个数据建模师都熟记的定义。

    • 实体是模型中的名词

    • 关系是动词,名词之间发生的动作

    • 动词短语定义了这些动作(这就是为什么它们被准确地称为动词短语,这不是一个有趣的名字)。

IDEF1X Notation文档中所述,对于关联表,将动词短语“通过”它们读取到关联另一端的父级。

  • APerson使一对多Bands,因此是Member

  • ABand由一对多People组成,它们是Members

  • APerson光顾 a Band,这使他们成为 a Fan(不仅仅是一个在表格Person中有一行的人)Fan

  • ABand取决于People, 谁是Fans

想出最短、最有意义的动词短语;不使用简单的词(要避免“包含”),对建模者来说是一个挑战。随意改进我提供的动词短语。

这是IDEF1X 中实体和键级别的派对数据模型。

不熟悉关系数据库建模标准的读者可能会发现我的IDEF1X 表示法很有用。

笔记

我所做的只是解决子类型;角色;如上所述的关系的基数。

  1. 当您评估您的第二批或您的交易实体时,子类型与角色的相关性对您来说会更加清晰(正如您所说,这里我们只有识别实体)。

  2. 标识符。这是值得一提的,不仅是为了阐明模型,还因为它是使用 IDEF1X 标识符以及它们部署的功能的一个很好的例子。您已经在您的模型中表明您理解(实线),我只是对其进行全面处理。

    • Person并且Band是 的子类型Party。它们也是 的角色Party。因此,我们从那一点向下使用PersonIdand ,而不是(即使它是)。BandIdPartyIdPartyId

    • 当 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 平台的实现细节,请参阅我的子类型文档

于 2011-01-22T07:33:38.083 回答
1

我认为这比你想象的要简单。您有两个对象 - 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 中。

于 2011-01-21T20:09:56.373 回答