我有一个数据库(用于宠物看护公司),其中包含以下表格:
- 顾客
- 紧急联络人
- 电话号码
- 电话类型
电话号码存储在一个单独的表中,以便为每位客户有效存储几乎无限数量的电话号码。除了主键之外,电话号码表还存储客户 ID 和电话类型 ID。我的问题是 - 允许紧急联系人与电话号码记录具有相同功能以向电话号码表“紧急联系人 ID”添加另一个字段的最佳方式是什么?或者我应该将紧急联系人存储在与客户相同的表中(并将其重命名为个人)?如果是这样,请告诉我如何在同一个表中的记录之间创建关系。
非常感谢,杰西卡
我有一个数据库(用于宠物看护公司),其中包含以下表格:
电话号码存储在一个单独的表中,以便为每位客户有效存储几乎无限数量的电话号码。除了主键之外,电话号码表还存储客户 ID 和电话类型 ID。我的问题是 - 允许紧急联系人与电话号码记录具有相同功能以向电话号码表“紧急联系人 ID”添加另一个字段的最佳方式是什么?或者我应该将紧急联系人存储在与客户相同的表中(并将其重命名为个人)?如果是这样,请告诉我如何在同一个表中的记录之间创建关系。
非常感谢,杰西卡
我会像存储电话号码一样存储它;在自己的桌子上。这使您能够存储多个号码,并且有些人可能有多个紧急联系号码。在设计数据库时,您总是想考虑可伸缩性,并为最复杂的情况做计划。例如,我想在宠物照看的情况下,您的很多客户都会通过口耳相传,您很可能会为多个客户使用同一个联系人。
您必须问自己一个问题:您应该在多大程度上真正尊重数据规范化规则?
我不确定该PhoneTypes
表将包含什么,但如果它是Mobile、Work、Home、iPhone之类的列表,那么您可能已经走得太远了:您不是在构建联系人应用程序,而是在构建一个宠物看护应用程序,可能有更重要的软件领域需要您的开发时间。
增加软件的复杂性是代价高昂的:实现功能的时间和复杂性都会逐渐增加,随之而来的是错误风险、维护成本,而且通常情况下,性能也会受到影响。
这些联系人详细信息实际上只是客户的属性。
一个客户可以有多个电话号码和多个紧急联系人。
通常这些应该按重要性顺序列出,所以如果有需要,你首先打电话给最相关的人。
如果没有更多信息,我将处理此问题的方式只是在我的客户表中留下 2 个备注字段,应用程序的用户可以在其中以她喜欢的任何方式输入该数据,因此她可以按正确的顺序列出它,将注释作为必要(仅在周一致电,客户妈妈,仅在上午 11:00 后致电等)。
如果您愿意,您可以进一步限制数据输入,例如有一个文本框,用户可以在其中输入详细信息,然后单击“添加”按钮,该按钮会将数据附加到字段中,例如通过使用分号或简单CrLf
地分隔记录。然后可以在分号或 CrLf 上拆分数据并显示在表单的列表框中,以便更好地呈现。
您可以以相同的方式处理客户电话号码和紧急联络号码。
这使事情变得简单:所有客户数据都在一个表中,而不是被拆分到多个表中,没有不必要的连接,它不会比使用多个表占用更多空间(实际上,它会节省空间)。它使报告变得容易(您可以简单地显示客户列表,这将显示所有客户的所有可用电话号码,而无需您做任何花哨的事情),它也使搜索变得容易。
对于外围数据,在单个字段中具有多个值是很常见的。
除非您绝对需要分离联系人,并根据它们制作复杂的报告或确保可以重复使用它们,否则您不必为每一个信息都创建表格。让应用程序用户输入与客户相关的内容。
如果需要,可以限制数据输入以对其进行格式化并检查其一致性,但最终,除非软件的目的是维护复杂的联系人列表,否则不要让它变得比它应该的更难。一点 VBA 和一些字符串操作就足以约束数据,允许按照与用户最相关的顺序重新排列它,并且通过避免一些复杂性,它将使您的应用程序更快捷。
无论如何,无论如何我都会从一些简单的东西开始,然后看看在多个表中拆分数据是否有意义。
避免过早的优化。
但是,如果你觉得你真的需要按书处理这个问题,我可能会按如下方式处理:
将所有内容存储在Contact
可能具有以下属性的表中:
ID
: 唯一的联系人 IDPhoneNumber
: 文本PhoneTypeID
: (不管是什么,如果它链接到你的 PhoneType 表)IsEmergencyContact
: 布尔值ContactName
: TEXT, freeform, 如何称呼联系人CustomerID
: 链接到客户表的外键Notes
:备忘录,有关联系人的任何有用信息Rank
: INTEGER,此联系人的可排序重要性等级如果您想将客户与联系人分离,以便可以为多个客户重新使用联系人,则需要一个中间表:
该Contact
表将变为:
ID
: 唯一的联系人 IDPhoneNumber
: 文本PhoneTypeID
: (不管是什么,如果它链接到你的PhoneType
表)ContactName
: TEXT, freeform, 如何称呼联系人Notes
:备忘录,有关联系人的任何有用信息和CustomerContact
表(使多对多关系成为可能):
CustomerID
: 链接到客户表的外键ContactID
: 链接到联系人表的外键IsEmergencyContact
: 布尔值Rank
: INTEGER,此联系人的可排序重要性等级要显示和管理联系人列表和紧急联系人列表,您只需根据IsEmergency
真假过滤显示信息的每个列表框或子表单。
现在,如果您希望同一个联系人拥有多个电话号码,您将不得不进一步拆分所有内容:
该Contact
表将变为:
ID
: 唯一的联系人 IDContactName
: TEXT, freeform, 如何称呼联系人Notes
:备忘录,有关联系人的任何有用信息一个PhoneNumber
表将包含:
ID
: 电话记录IDContactID
: 链接到联系人表的外键PhoneNumber
: 文本PhoneTypeID
: (不管是什么,如果它链接到你的 PhoneType 表)Notes
:备忘录,有关此特定电话号码的任何有用信息现在您有 4 个表格来存储您需要的所有信息并以您想要的任何方式共享,因此客户可以有多个联系人(紧急或非紧急情况),联系人可以有多个电话号码,联系人可以跨客户共享(所以一个客户的联系人是另一个客户的紧急联系人):
Customer
Contact
PhoneNumber
CustomerContact
正如我所说,以正确的方式进行操作会带来比您真正需要的复杂得多的复杂性。
小心不要过早地构建复杂性。预测更坏的情况很好,但通常,这意味着您过早地进行优化,因此将时间花在软件的某个区域上,而该区域并不像您的应用程序的核心那么重要。
你总是要问自己:我应该花 2 天时间来实现它还是花 2 天时间改进 UI、测试或添加代码以确保数据完整性等?
通常情况下,YAGNI
您的第一直觉(将客户和联系人存储在一个表中)是正确的。如果你仔细想想,客户和联系人都是人。只是客户和紧急联系人都是人的特殊情况。我们可以使用关系数据库对此进行建模。
让我们创建一个表来保存有关人员的信息:
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。