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