有关基础设计,首次数据库设计的建议


8

我正在学习成为一名Java开发人员的课程。

该课程涉及使用数据库,但是不幸的是,我们从未真正设计任何数据库。

大多数时候,我们会获得预制数据库,并且必须在其上实现代码以插入,更新,读取或删除数据。

但是,当我进行最后的测试时,很可能我会做一些涉及数据库的事情,因此我想尝试设计一些较小的项目以摆脱设计的束缚,因为我注意到良好的数据库设计在编写代码以使用它。

我希望这里允许这些类型的问题,并且不会太广泛。


这是东西简单做了一个小设计,我clubsmembersaddressesphonenumbers

  • 将有多个俱乐部。
  • 每个俱乐部将有多个成员(明显)
  • 成员不能成为多个俱乐部的成员
  • 成员可以具有多个电话号码和电子邮件地址
  • 会员只能有一个地址
  • 一个地址可以属于不同的成员(夫妇或兄弟姐妹)

我最大的困惑:

  • 如果我想在其中添加Club描述所有者(也将是成员)的列,那么最好是在没有两次列出相同成员的情况下的最佳方法?

  • 我应该将所有表格放在id的自动增量上,还是一个坏主意?(好处/缺点?)

  • 如果在“外键”选项卡中添加外键,这些外键会自动对应于正确的表吗?还是也必须将它们添加到列中?(见图2)

  • 而我在所有可能noobiest问题...我是否把的外键phonenumberemail在各自的表链接到一个PERSON_ID或者我应该把phoneNumber的和电子邮件标识的在人的表?

(我对图片中的语言不是英语表示歉意,希望这不是太大的问题)

设计

外键

Answers:


11

对您个人问题的回答

如果我想在其中添加Club描述所有者(也将是成员)的列,那么最好是在没有两次列出相同成员的情况下的最佳方法?

如果-如您的规范中所述- a Person can be a Member of only one Club且您希望将该数据简单地存储为true或false,则一种选择是在表中添加a BIT(1)BOOLEANTINYINT)列Person,您不妨调用此列IsClubOwner。这样,您可以一次注册一个确定的俱乐部所有者的事实。除此之外,该方法还允许保留多个人作为同一家具乐部的所有者。您可以在图1中看到此方法的逻辑层次描述。

但是,您正在寻找最佳方法,根据我的经验,这种方法需要开发出更加可扩展和通用的结构。在这方面,请遵循以下针对这些和其他要点的建模练习的进展,在标题为“涵盖其余规格”,“多个俱乐部成员的人”和“成员和所有者为独立实体类型”的部分中。

我应该将所有表格都放在id或的自动增量上吗?(好处/缺点?)

如果你面对一个明确的指示表的定义具有这样的特性的列要求,并且该列有一个有效的上下文意思或服务就像是一个特定的目的替代广泛的自然PRIMARY KEY(PK),那么,您应该以这种方式进行。

否则,如果您没有上述要求,那么我认为这是不必要的,因为您必须在数据库中存储和管理无意义的额外列,以及(也许吗?)额外的INDEX。

像往常一样,您必须分析每种情况及其整体影响,以便决定如何进行。

如果在“外键”选项卡中添加外键,这些外键会自动对应于正确的表吗?还是也必须将它们添加到列中?

在这方面,我的建议是手动创建数据库结构,编写自己的DDL语句,直到您牢牢掌握该主题。如果这样做,您将更容易理解图形工具正在“幕后”执行的过程。

例如,对我而言,创建如下语句:

CONSTRAINT FK_PersonPhoneNumber_to_Person FOREIGN KEY (PersonId)
REFERENCES Person (PersonId)

比使用GUI工具执行此类任务更具指导性,尤其是在您正在构建第一个设计时。

而我可能是最noobiest所有的问题...我是否把的外键phone_numberemail在各自的表链接到一个person_id或我应该把phone_numberemail ids在人的表?

就我个人而言,我认为这个问题以及您所有其他问题都是完全有效的并且可以根据具体情况而定

回到涉及我们的技术方面,这个精确的查询提供了一个很好的机会来审查以下两个主张:

  • A Person can be reached through zero-one-or-many PhoneNumbers
  • A PhoneNumber can be used to reach one-to-many People

所以,我们可以得出这样的结论之间的许多一对多的关系PersonPhoneNumber,因此,我建议在创建关联表命名PersonPhoneNumber,以表示你的数据库,所述的关系。该表的PK应该由两个不同的列组成:(PersonId指向的FOREIGN KEY [FK] Person.PersonId)和PhoneNumber(指向的FK PhoneNumber.Number)。有关以上所有内容的逻辑级别描述,请参见图1

另一方面,让我们研究以下两个命题:

  • A Person can be contacted via zero-one-or-many EmailAddresses
  • An EmailAddress can be used to contact exactly one Person

然后,是的,您应该PersonEmailAddress表中设置对FK的引用,并且该表也应该具有复合PK,该复合PK由列PersonId和组成Address。通过这种方式,可以保证相同的组合EmailAddress.PersonId,并EmailAddress.Address可以一次插入。

如果您还希望确保一个给定EmailAddres.Address值可以存储在一个单独的行中,则只需为该列建立一个UNIQUE CONSTRAINT

建议的逻辑数据模型

为了更清楚地揭示我的建议,我包括了四个不同的IDEF1X [1]逻辑模型,分别在图1图2图3图4中显示。我将在相应的部分中解释每个功能中显示的最相关的功能。您也可以从Dropbox下载 PDF,该PDF将大多数讨论中的元素集成到一个模型中。

涵盖您剩余的规格

联系人和地址

让我们检查以下两个与人员地址相关的断言(略有措辞):

  • A Person can only have one Address
  • An Address can belong to different People (couples or siblings)

因此,为了应对这些限制,您可以选择实现类似于图1所示的数据模型。

图1.俱乐部和会员数据模型-第一规格

考虑到引用的模型,您应该遵循以下步骤:

  1. 创建一个称为PersonAddress修复Person和之间关系的表Address。设置列PersonIdAddressId作为此表的复合PK。

  2. 为该PersonAddress.PersonId列配置UNIQUE CONSTRAINT,以确保可以在该表的最多一行中插入特定值。从逻辑上讲,这种情况意味着PersonAddress.PersonId已经成为另一个关键字[2]

  3. 如果该值AddressId在确定PersonAddress插入的尝试还没有被已经存储,然后让插入继续,否则,当这种价值在一排已经存在,你必须检查(一)PersonId谁已经注册了AddressId也注册为Marriage.WifeId如果PersonId是男性(通过导出的基准Person.GenreCode(b),PersonIdMarriage.HusbandIdPersonId是女性时(也是通过得出),则是Person.GenreCode。如果在适当的情况下满足了这些条件之一,则应继续执行INSERT。

  4. 如果不满足上述条件,则仍有PersonAddress插入尝试成功的机会。您必须检查PersonId所述插入尝试中涉及的值是否Progeny.ParentIdPersonId已注册的共享至少一个值PersonAddress.AddressId。如果满足这个条件,那么就意味着它们保存Siblings在数据库中,所以这个INSERT必须成功。

与在任何关系数据库实现中一样,您应该认真考虑DMLACID Transactions中执行操作,以便可以保护正在使用的数据的完整性一致性

满足您在评论中添加的要求:地址和电话号码同时适用于俱乐部和人员

如果您希望有机会提供地址电话号码同时服务于个人俱乐部,则可以利用超类型与子类型的关系。如果您有兴趣,这里提供了一个答案,在此我对这种结构进行了更详细的介绍。

在当前情况下,您可以定义一个名为的新实体Person并将其Club作为子实体Party,作为法律实体中常用的术语来代表(a)一个人或(b)一群人(如意义6所示)。使用此方法,Addresses(和PhoneNumbers)和People和之间的关系Clubs将通过Party父类型定义。有关该建议的描述,请参见图2

图2.俱乐部和会员数据模型-第二规格

派对和地址

因此,我们可以在此新模型中阅读:

  • A Party keeps zero-one-or-many Addresses
  • An Address is kept by one-to-many Parties

因此,存在涉及实体PartyAddress通过PartyAddress实体表示的多对多关系。

派对和电话号码

此外,我们可以解释为:

  • A Party is reached through zero-one-or-many PhoneNumbers
  • A PhoneNumber is used by one-to-many Parties

这就是为什么我添加了PartyPhoneNumber实体来描述在PartyPhoneNumber实体类型之间生效的多对多关联的原因。

派对和俱乐部或个人

然后,还可以看到:

  • A Party is either a Club or a Person

因此,Party提供了一个连接任一 Clubs PeopleAddresses(或PhoneNumbers)。

多个俱乐部成员

正如@aldwinaldwin在他的回答中提到的那样,如果您想提供一个成为多个俱乐部成员的功能,那么您可以包括一个表,该表将充当另一个多对多关系,这一次很自然,互连和。ClubMemberPersonClub

我要添加到上面这个表也可以在存储任何具体的目标有用的作为业主多的俱乐部,通过包括已经提到的手段IsClubOwner布尔列。实际上,可以说这个新表本身就是整数实体类型的表示。

如在展示图3,如表需要的列的由复合PK ClubIdMemberId(一个角色名称[3]提供给PersonId),以及这些列必须也被定义为指向FKS,相应地,对ClubPerson

图3.俱乐部和会员数据模型-作为多个俱乐部成员的人

更具适应性的结构

使用此设置,您还可以遵守最初的规则,该规则指出a Person can be a member of only one Club,但您只需要向该MemberId列添加UNIQUE CONSTRAINT ,这样就可以在不超过一种情况下输入某个值。所以,你可以注意到,这种结构更有适应性,在所示的图1通过删除唯一约束(或指数),因为你会打开允许一个的上述功能的人成为会员不同的俱乐部在同时。

成员和所有者分别为实体类型

如你所知,关于角色的存储几个事实通过进行作为业主一的俱乐部 -还有在其单纯的所有脑干真或假的属性-可以是非常有利的。例如,你可能想保留生效日期,其中一个明确的成为了 主人一的俱乐部,因此你可以通过引入称为一个独立的实体型管理这种情况ClubOwner,在所呈现如图4

图4.俱乐部和会员数据模型-会员和所有者作为单独的实体类型

一旦基于这种新的实体类型构造了一个表,就可以添加表示当a PersonOwnera 时独有的特征的拟合列Club。如图所示,该表将包含一个由FK列组成的PK,该列引用Person.PersonIdClub.ClubId,这样,ClubOwner.OwnerId(或ClubOwner.PersonId,如果愿意)的任何组合ClubOwner.ClubId都可以插入到一个机会中。

当然,如果返回的标量值可以评估为true或false,则使用这种配置,如果a PersonOwner特定的Club,您仍然可以以布尔形式导出。


笔记

1.信息建模集成定义(IDEF1X)是一种高度推荐的数据建模技术,该技术已于1993年12月由美国国家标准技术研究院(NIST)定义为标准。它坚实基础的(一)一些理论文章的撰写由始发的的关系模型,即EF科德博士 ; (b)由陈PP博士开发的实体关系理论;以及(c)Robert G. Brown创建的逻辑数据库设计技术。值得注意的是,IDEF1X形式化通过的方式一阶逻辑

2. ALTERNATE KEY是一个属性(或属性的组合),具有唯一标识一个实体出现但未被选择为相关实体类型的PK的值;每种实体类型可以具有零个,一个或多个ALTERNATE KEYS。在IDEF1X模型中,将它们表示为“ AK”加上其各自的编号,例如AK1,AK2等。它们通常通过UNIQUE CONSTRAINT(或UNIQUE INDEX)以SQL DDL结构实现。

3. 角色名称是分配给FK属性的符号(或别名),目的是表达它们在各自实体范围内的含义。Codd博士自1970年以来就在其开创性论文“大型共享数据库的数据关系模型”中建议使用它们。就其本身而言,IDEF1X(保持忠实于关系实践)也提倡角色命名。


2
  1. 如果所有者始终是其俱乐部的成员。将ownerId添加到俱乐部表中,然后将personId放在所有者成员中。
  2. 自动递增ID是好的。您可以添加另一个字段“代码”,将会员代码放在那里的俱乐部卡上。
  3. 应该自动确定(我认为)
  4. 将personId放在电话号码和电子邮件表中。

...您不能成为多个俱乐部的成员吗?如果可以,请创建带有clubId和personId的表ClubMember。这样,您可以将一个人连接到多个俱乐部。


1
如果我想让我的俱乐部打个电话号码怎么办?我clubId也要输入电话号码,并将club或person设置为null吗?
Vahx

我不会“过度”分离所有对象(数据标准化)。只需在俱乐部桌子上放一个电话号码即可。标准化是好的,但是过多的标准化会导致问题。
aldwinaldwin

1
但假设我确实想这样做?我以地址为例,会员有一个地址,但俱乐部也需要一个地址
Vahx 2015年

1
创建一个地址记录,并将addressId放在club中。因为俱乐部有1个地址,所以会员有1个地址。对于电话号码,您需要将personId放在电话号码记录中以具有1到许多。.....您可以使一个表personPhoneNumber(personId,phonenumberId)+表clubPhoneNumber(clubId,phonenumberId)成为一个多对多关系。
aldwinaldwin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.