与2个表

时间:2017-09-10 10:56:03

标签: database database-design relational-database

实施例。在我的系统中,我有一个对象,由几个其他类型的对象用于1对1关系。让我们调用使用Address的对象,以及使用它的两个对象Company和Person。每个公司和个人都有一个地址,每个地址在系统中都是唯一的,因此每个地址都由个人或公司引用。

我有两个问题。

问题1)这种关系叫什么?我在网上找到的1对1关系的所有例子都只在两个表之间,而这是从1到1的三种关系。

问题2)哪种表结构最能捕获这种关系?我看到至少有两个看起来有缺陷的潜在设计。

设计a)使用两个可以为空的外键,其约束条件是至少有一个不为空。像复合外键一样。

- Company -
pkCompanyId
...

- Person -
pkPersonId
...

- Address -
pkAddressId
fkPersonId <nullable>
fkCompanyId <nullable>
...

设计b)每个公司和个人都识别它使用的地址。

- Company -
pkCompanyId
fkAddressId
...

- Person -
pkPersonId
fkAddressId
...

- Address -
pkAddressId
...

设计a)看起来像是对我的更常规的外键使用,因为正在使用的对象标识引用它的对象,但我还没有看到任何这样的例子,这是用这样的多个外键完成的

设计b)看起来与正常建模1对1关系的方式相反。

在我看来,在传统的1对1关系(下面)中,fkPersonId是一个不可空的唯一外键有助于在实际表结构中强制执行1对1关系(它保证每个地址都是由不引用其他地址的单个Person引用。我的设计都没有实现这一点。在设计中a)必须确保fkCompanyId或fkPersonId中的一个且只有一个为空以确保一致性。在设计b)中,必须确保公司或个人中的fkAddressId在任一表中都不重复。这让我怀疑我在这里犯了错误。

- Person -
pkPersonId
...

- Address -
pkAddressId
fkPersonId
...

没有太多努力,我可以看到其他设计,例如在地址中使用guid for pkCompanyId和pkPersonId以及单个外键但我再次在我研究的任何在线资源中都没有看到这个策略的任何示例。

我显然已经超出了我对数据库设计的有限知识,请使用一些指导。处理这个问题的最佳方法是什么?

更新回应Walter Mitty的回答

我认为单表继承不适合我的情况。虽然我在这里使用了示例公司和人员,但在我的实际应用程序中,这些都是大型复杂表格,除了它们都拥有地址之外没有任何共同之处。他们的数据不仅非常不同,而且代表了完全不同的概念。

每个具有相同类型实例的实际实体是Organization,Project和ProjectElement。组织代表许可使用系统的公司。 Project表示由特定组织的用户创建的项目,ProjectElement表示一段项目数据。

他们都拥有一个实例的东西是一个Settings对象。默认设置在组织级别提供。创建项目时,它会获得组织设置的副本。项目中的组件获得项目设置的副本。

此体系结构支持多种用例,包括修改组织的设置时,这些更改仅影响新项目,而不影响已创建的项目。 ProjectElements继承Project的设置,但可以选择覆盖特定的Project设置。

进一步的复杂性包括组织,项目和ProjectElement不只有一个共享类型的实例,而是几个。有几种不同类型的Settings对象,每个对象都有自己的表。如果不能将共享类型的实例的ID用作引用对象的主键,那么这将使其变得不可行。我也在使用当前不支持视图的Entity Framework Core ORM。

你的回答非常有用,给了我很多思考,但到目前为止我觉得我的设计2最能达到我的要求。设计2是否有任何本质上不合理的东西使它不合适?

1 个答案:

答案 0 :(得分:1)

您的问题看起来像是类型和子类型(或类和子类)的情况。在我尝试处理你的两个问题之前,我会尝试重新构建它,作为两个关系。

首先,我要发明一个新的实体,我打电话给&#34;联系&#34;。系统中的每个地址都由联系人引用,每个联系人都有一个或多个地址。

每个联系人都是个人或公司,但不是两者。

现在,至少在概念上,我们首先将地址与联系人连接,然后我们将该联系人与个人或公司联系起来。在逻辑和物理层面,这可能是过度的。也就是说,它可能会增加复杂性而不会增加价值。我不能强调这一点。

但概念清晰度本身就是有价值的。

现在回答你的问题1。

联系人和地址之间的关系只是一个经典的&#34; has-a&#34;风格关系,就像你以前见过的很多。

但是,联系人与任何人或公司之间的关系是一种不同的关系,一种你以前可能没见过的关系。它被各种名字称呼,这是我对你的问题1的回答。

它有时被称为IS-A关系&#34;。在ER建模中,它经常以名称&#34;专业化/概括化为基础。关系。在对象建模中,它经常被称为&#34;类/子类关系&#34;虽然流行语&#34;派生类&#34;或者&#34;扩展课程&#34;有时使用。它还与继承的对象概念相关联。

然而,关于对象建模的一个警告。如果要在同一个项目中进行对象建模和数据建模,最好对这两个项目有很深入的了解,以及每个项目如何为项目增加价值。否则,你可能会陷入一种思维模式或其他只是难以理解或无用的陷阱。比我聪明的人多次陷入这个陷阱。

现在提出第二个问题。有两种方法可以为这种情况设计表格。一个被称为&#34;单表继承&#34;另一个被称为&#34; class-table-inheritance&#34;。我将连字符放入的原因是这个区域中有这两个主题的标签,查看这两个标签下的问题和信息可能会对您有所帮助。

单表继承。

我们将有两个表,一个用于地址,一个用于联系。

地址:

AddressID (PK)
ContactID  (FK references Contact)
Street Address
City,
State,
Zipcode,
etc.

联系人:

ContactID (PK)
ContactType  (Person or Company, coded)
First Name
Last Name,
Company Name,
etc.

在人员的情况下,公司名称将为NULL,在公司的情况下,名字,姓氏将为NULL)。

类表继承

我们将有四个表,地址,联系人,人员和公司

地址:

AddressID (PK)
ContactID  (FK references Contact)
Street Address
City,
State,
Zipcode,
etc.

联系人:

ContactID  (PK)

人:

ContactID  (PK, and FK references Contact)
First Namme,
Last Name,
etc.

公司:

ContactID (PK and FK references Contact)
Company Name
etc.

对于您的情况,我建议单表继承。但对于非常复杂的IS-A关系案例,类表继承可以更好地解决。