如何将子类型应用于SQL Server数据库?

时间:2010-10-08 20:26:13

标签: sql-server subtype supertype

我正在制定一个可以注册投诉的计划。有三种类型的投诉:internal(来自员工的错误),external(来自其他公司的错误)和supplier(供应商提出的错误)。它们包含无法共享的不同数据。我目前有4张桌子(投诉,员工,公司和供应商)。这是表格的可视化:

我对子类型有基本的了解,但我似乎无法将它们从ERD转换为实际的SQL Server数据库,或者至少在这种情况下。这大致是4个表的外观(省略了不相关的属性):

投诉
ComplaintId PK

员工
EmployeeId PK
EmployeeName

公司
CompanyId PK
公司名称

供应商
SupplierId PK
SupplierName

在注册投诉时,错误由3种类型中的任何一种产生,并且它们都存储不同的信息。在这种情况下,存储信息的最佳方法是什么?我想过在投诉表中放置2个鉴别符:ComplaintTypeId所以我可以指出要检查哪个表以及我需要什么,但这不是很干净也没有效率。< / p>

请协助。

5 个答案:

答案 0 :(得分:18)

在这个主题上看到一些非常好的资源:

基本上有三种众所周知的方法:

  • 每个子类的表格
  • 每个层次结构的表
  • 每种混凝土类型的表格

每个人都有利有弊,在某些情况下闪耀,在其他情况下很糟糕 - 研究资源,看看哪三种最适合你的需求。

答案 1 :(得分:4)

我强烈建议您不要使用“2鉴别器”方法。您将有效地拥有一个指向三个表之一的外键列,具体取决于ComplaintType字段。如果这样做,您将绕过SQL Server提供的参照完整性检查以及外键附带的所有好处。在我以前的工作中,有一个名为EntityTypeIndexLabel的表,它是一个“桥表”,它将IndexLabels(基本上是元数据)附加到各种“实体”,这些实体是许多不同的潜在表(Document,Binder,Workflow等......)。这简直太糟糕了。此表中的FK可以指向许多不同的表。孤立的记录可能随处可见。必须实现额外的逻辑以确定要加入的表。加入是一般的写作痛苦。这是各种头痛。

我认为你的两个选择是:

投诉中的

-3列:EmployeeComplaintID,CompanyComplaintID,SupplierComplaintID。 ComplaintID在所有表中应该是唯一的(想想这里的GUID而不是IDENTITY列)。 Complaint中的每一行只会填充其中一个ID,另外两行将为NULL。然后,您可以在每个查询中简单地对这些表进行LEFT OUTER JOIN以获取所需的数据。

- 包含每种投诉类型所需的所有可能字段的巨型表格,将其他投诉类型的未使用字段设置为NULL。

答案 2 :(得分:1)

主要问题是您需要某种“序列号”来唯一标识投诉,无论哪种类型?基本上,那么,你需要一个表格用于每种类型的投诉(我认为你会有),以及带有ComplaintId的主“投诉”表。每个特定于类型的表都有一个Complaint.ComplaintId的外键。您可能会发现在Complaint中有一个“类型”字段很有用,但模型并不需要这样做。

答案 3 :(得分:1)

您可以拥有与所有三个子类型表 - 员工,公司和供应商的PK的FK关系的投诉SubTypeID。

答案 4 :(得分:1)

回应您对接受的答案的评论:

以下是检查以确保三个键中只有一个具有数据的方法:

alter table complaint_master 
    add constraint loc_attribute_has_one_value 
    check ( 
        (case when complaint_employee is null then 0 else 1 end) + 
        (case when complaint_supplier is null then 0 else 1 end) + 
        (case when complaint_external is null then 0 else 1 end)  = 1 
    );