1

我正在寻找有关设计具有要与其他几种不同实体类型相关的通用实体的数据库的建议。可怕的介绍句,我知道……所以请让我举例说明。

考虑到我有两个不同的实体Employees 和Customers 表defs:

Employees
----------
EmployeeID int PK
FirstName varchar
LastName varchar
... other Employee specific fields

Customers
----------
CustomerID int PK
FirstName varchar
LastName varchar
... other Customer specific fields

更好的设计可能在相关的基表中包含公共字段 FirstName 和 LastName,但这不是我正在努力解决的部分。

现在,考虑我希望能够为我的员工和客户存储无限数量的地址和电话号码,并定义表:

Addresses
----------
AddressID int PK
AddressLine varchar
City varchar
State varchar
PostalCode varchar

PhoneNumbers
-------------
PhoneNumberID int PK
PhoneNumber varchar
PhoneExtension varchar

然后是另外两个表格,将地址和电话号码与员工联系起来:

EmployeeAddresses
------------------
EmployeeAddressID int PK
EmployeeID int FK Employees.EmployeeID
AddressID int FK Addresses.AddressID
EmployeeAddressType enum

EmployeePhoneNumbers
---------------------
EmployeePhoneNumberID int PK
EmployeeID int FK Employees.EmployeeID
PhoneNumberID int FK PhoneNumbers.PhoneNumberID
EmployeePhoneNumberType enum

还有两个类似的表 CustomerAddresses 和 CustomerPhoneNumbers,用于将 Addresses 和 PhoneNumbers 关联到 Customers 表。Addresses 和 PhoneNumbers 的任何特定于员工或特定于客户的方面,例如上面的 EmployeeAddressType,也在最后四个表中。

根据我对 Internet 的研究,这种设计称为 Table-Per-Type (TPT) 或 Table-Per-Subclass (TPS)。并且多态优势似乎很有吸引力,例如,我可以将 AddressLine2 添加到 Addresses 表中,我的 Employess 和 Customers 都会自动获得额外地址行的好处。

这些关于 TPT 的消息来源指出的缺点是查询速度较慢且难以实现。现在我相当开放的征求意见...

我没有考虑其他哪些缺点?您在尝试维护和改进基于此设计的应用程序时会遇到什么问题?最后,上面的设计是大多数有经验的数据库设计师会使用的吗?

谢谢。

4

4 回答 4

1
  1. 使用单表继承开始。它是最简单、最容易和最快的。

  2. 使用派对模式。个人和组织都是当事人,可以扮演客户或员工的角色。

  3. 将电子邮件地址、电话号码、网站和邮寄地址都视为“联系方式”或地址的子类型。

  4. 如果您使用 JBoss Hibernate (java) 或 NHibernate (.net) 之类的工具,那么这将为您完成大部分工作。

于 2013-04-26T17:10:07.733 回答
0

最好从 People 表开始,然后是 customers 表、employees 表等。然后,电子邮件地址、地址和电话号码将与 people 表相关,而不是与 customer 或其他一些专门的表相关。

与多个父表相关的一个地址表的问题是您无法设置适当的外键约束,并且总是会得到错误的数据。

您可以使用单独的表正确创建外键,但查询变得更加困难(假设您需要了解 CA 中的每个人),您会为最终属于多个类别的人(员工也可能是客户)获得重复记录,并且它是当需要更改表结构时,更难确保表全部更新。

于 2013-04-26T18:26:50.377 回答
0

当前数据库设计的一个缺点是您的数据库不会阻止员工拥有 2 个或更多家庭地址。它也不会阻止客户对此没有地址。

您可以通过更改 EmployeeAddresses 表(PK = EmployeeID, EmployeeAddressType)上的复合主键来防止创建多个家庭地址。但是,如果您使用的是 ORM,它们中的许多只有在 PK 为一列时才能发挥出色。

于 2013-04-26T18:42:46.403 回答
0

如前面的回复中所述,Employees 和 Customers 都是 People 类的子类。这两个子类可能不是相互排斥的。

有一种技术,称为类表继承。在这种技术中,将有三个表,人员、员工和客户。所有人共有的属性(例如地址)将位于“人员”表中。

您可以通过访问此标签 并在“Info”标签下查看来获取详细信息。

于 2013-04-26T19:34:58.080 回答