2

我有一个数据库(用于宠物看护公司),其中包含以下表格:

  • 顾客
  • 紧急联络人
  • 电话号码
  • 电话类型

电话号码存储在一个单独的表中,以便为每位客户有效存储几乎无限数量的电话号码。除了主键之外,电话号码表还存储客户 ID 和电话类型 ID。我的问题是 - 允许紧急联系人与电话号码记录具有相同功能以向电话号码表“紧急联系人 ID”添加另一个字段的最佳方式是什么?或者我应该将紧急联系人存储在与客户相同的表中(并将其重命名为个人)?如果是这样,请告诉我如何在同一个表中的记录之间创建关系。

非常感谢,杰西卡

4

3 回答 3

0

我会像存储电话号码一样存储它;在自己的桌子上。这使您能够存储多个号码,并且有些人可能有多个紧急联系号码。在设计数据库时,您总是想考虑可伸缩性,并为最复杂的情​​况做计划。例如,我想在宠物照看的情况下,您的很多客户都会通过口耳相传,您很可能会为多个客户使用同一个联系人。

于 2013-08-22T01:09:44.780 回答
0

您必须问自己一个问题:您应该在多大程度上真正尊重数据规范化规则?

我不确定该PhoneTypes表将包含什么,但如果它是MobileWorkHomeiPhone之类的列表,那么您可能已经走得太远了:您不是在构建联系人应用程序,而是在构建一个宠物看护应用程序,可能有更重要的软件领域需要您的开发时间。

增加软件的复杂性是代价高昂的:实现功能的时间和复杂性都会逐渐增加,随之而来的是错误风险、维护成本,而且通常情况下,性能也会受到影响。

这些联系人详细信息实际上只是客户的属性。

一个客户可以有多个电话号码和多个紧急联系人。
通常这些应该按重要性顺序列出,所以如果有需要,你首先打电话给最相关的人。

如果没有更多信息,我将处理此问题的方式只是在我的客户表中留下 2 个备注字段,应用程序的用户可以在其中以她喜欢的任何方式输入该数据,因此她可以按正确的顺序列出它,将注释作为必要(仅在周一致电客户妈妈,仅在上午 11:00 后致电等)。

如果您愿意,您可以进一步限制数据输入,例如有一个文本框,用户可以在其中输入详细信息,然后单击“添加”按钮,该按钮会将数据附加到字段中,例如通过使用分号或简单CrLf地分隔记录。然后可以在分号或 CrLf 上拆分数据并显示在表单的列表框中,以便更好地呈现。
您可以以相同的方式处理客户电话号码和紧急联络号码。

这使事情变得简单:所有客户数据都在一个表中,而不是被拆分到多个表中,没有不必要的连接,它不会比使用多个表占用更多空间(实际上,它会节省空间)。它使报告变得容易(您可以简单地显示客户列表,这将显示所有客户的所有可用电话号码,而无需您做任何花哨的事情),它也使搜索变得容易。

对于外围数据,在单个字段中具有多个值是很常见的。
除非您绝对需要分离联系人,并根据它们制作复杂的报告或确保可以重复使用它们,否则您不必为每一个信息都创建表格。让应用程序用户输入与客户相关的内容。
如果需要,可以限制数据输入以对其进行格式化并检查其一致性,但最终,除非软件的目的是维护复杂的联系人列表,否则不要让它变得比它应该的更难。一点 VBA 和一些字符串操作就足以约束数据,允许按照与用户最相关的顺序重新排列它,并且通过避免一些复杂性,它将使您的应用程序更快捷。

无论如何,无论如何我都会从一些简单的东西开始,然后看看在多个表中拆分数据是否有意义。
避免过早的优化。

但是,如果你觉得你真的需要按书处理这个问题,我可能会按如下方式处理:

将所有内容存储在Contact可能具有以下属性的表中:

  • ID: 唯一的联系人 ID
  • PhoneNumber: 文本
  • PhoneTypeID: (不管是什么,如果它链接到你的 PhoneType 表)
  • IsEmergencyContact: 布尔值
  • ContactName: TEXT, freeform, 如何称呼联系人
  • CustomerID: 链接到客户表的外键
  • Notes:备忘录,有关联系人的任何有用信息
  • Rank: INTEGER,此联系人的可排序重要性等级

如果您想将客户与联系人分离,以便可以为多个客户重新使用联系人,则需要一个中间表:

Contact表将变为:

  • ID: 唯一的联系人 ID
  • PhoneNumber: 文本
  • PhoneTypeID: (不管是什么,如果它链接到你的PhoneType表)
  • ContactName: TEXT, freeform, 如何称呼联系人
  • Notes:备忘录,有关联系人的任何有用信息

CustomerContact表(使多对多关系成为可能):

  • CustomerID: 链接到客户表的外键
  • ContactID: 链接到联系人表的外键
  • IsEmergencyContact: 布尔值
  • Rank: INTEGER,此联系人的可排序重要性等级

要显示和管理联系人列表和紧急联系人列表,您只需根据IsEmergency真假过滤显示信息的每个列表框或子表单。

现在,如果您希望同一个联系人拥有多个电话号码,您将不得不进一步拆分所有内容:

Contact表将变为:

  • ID: 唯一的联系人 ID
  • ContactName: TEXT, freeform, 如何称呼联系人
  • Notes:备忘录,有关联系人的任何有用信息

一个PhoneNumber表将包含:

  • ID: 电话记录ID
  • ContactID: 链接到联系人表的外键
  • PhoneNumber: 文本
  • PhoneTypeID: (不管是什么,如果它链接到你的 PhoneType 表)
  • Notes:备忘录,有关此特定电话号码的任何有用信息

现在您有 4 个表格来存储您需要的所有信息并以您想要的任何方式共享,因此客户可以有多个联系人(紧急或非紧急情况),联系人可以有多个电话号码,联系人可以跨客户共享(所以一个客户的联系人是另一个客户的紧急联系人):

  • Customer
  • Contact
  • PhoneNumber
  • CustomerContact

正如我所说,以正确的方式进行操作会带来比您真正需要的复杂得多的复杂性。

小心不要过早地构建复杂性。预测更坏的情况很好,但通常,这意味着您过早地进行优化,因此将时间花在软件的某个区域上,而该区域并不像您的应用程序的核心那么重要。
你总是要问自己:我应该花 2 天时间来实现它还是花 2 天时间改进 UI、测试或添加代码以确保数据完整性等?

通常情况下,YAGNI

于 2013-08-22T02:04:33.710 回答
0

您的第一直觉(将客户和联系人存储在一个表中)是正确的。如果你仔细想想,客户和联系人都是人。只是客户和紧急联系人都是人的特殊情况。我们可以使用关系数据库对此进行建模。

让我们创建一个表来保存有关人员的信息:

create table tblPeople (
  ID autoincrement primary key
, FirstName varchar(100)
, LastName varchar(100)
, Notes memo
)

现在让我们有一个表格来保存有关客户的信息,但强制执行客户也必须是人的事实:

create table tblCustomers (
  ID long primary key
  constraint Customers_ID
  references tblPeople (ID)
, EmergencyContactID long
  constraint Customers_EmergencyContactID
  references tblPeople (ID)
)

这称为一对一关系,用于实现专门化——如面向对象编程中的继承。

你在这里有一个选择。你想让每个人拥有任意数量的任意类型的电话号码吗?这显然更通用,更强大。但也更复杂。还是您想返回并为每个人存储固定数量的电话号码?

假设你想做前者只是为了一路走下去。在这种情况下,您需要一个表格来保存电话号码:

create table tblPhoneNumbers (
  ID autoincrement primary key
, PhoneNumber varchar(15)
)

请注意,我们在这里没有具体说明它是什么类型的电话号码。那部分是下一个:

create table tblPhoneNumberTypes (
  ID autoincrement primary key
, PhoneNumberType varchar(20) not null
)

现在我们将每个人与一个电话号码相关联并输入:

create table tblPeople_to_PhoneNumberTypes_to_PhoneNumbers (
  PersonID long not null
  references tblPeople (ID)
, PhoneNumberTypeID long not null
  references tblPhoneNumberTypes (ID)
, PhoneNumberID long not null
  references tblPhoneNumbers (ID)
, constraint People_to_PhoneNumberTypes_to_PhoneNumbers_PK
  primary key (
    PersonID
  , PhoneNumberTypeID
  , PhoneNumberID
  )
)

在这里,每个人(因此每个客户和每个紧急联系人)都可以拥有任意数量的任意类型的电话号码。因此,这实际上是一个多对多对多的链接表。我相信这是您的联系电话类型电话号码模型的关键(或者我们说“秘诀”)。

在像上面这样的链接表中,我更喜欢使用多列主键,因为我觉得整数主键列没有用处。这里的主键强制每个人和电话号码组合应该只列出一次,并具有一种电话号码类型。

请注意,以上都是有效的 Access ANSI-92 SQL。

于 2013-09-28T18:15:54.413 回答