“一对多”建模问题

时间:2009-03-11 16:39:51

标签: sql database-design orm data-modeling

建模以下内容的最佳方式是什么......

假设我有两个对象:AgencyPublisher,两者都与Employee有一对一的关系。这是真正的1对n关系,因为每个Employee只能用于一个Agency或一个Publisher。让我们进一步假设我不能介绍一个 保持1对n关系的超类型(例如Employer)。

我首选的解决方案是在Employee中使用外键,该外键可以链接到AgencyPublisher的主键(我的所有主键都是64位ID,整个数据库都是唯一的)。但是,现在我无法在Employee中指明这是Agency还是Publisher关系,从而无法映射双向关联。

我的另一个选择是使用两个表AgencyEmployeePublisherEmployee,然后可以将它们链接为传统的1对n双向关联。

在这种情况下,您认为最佳做法是什么?

更新:感谢您在如此短的时间内做出的出色回应!您如何看待以下解决方案:EmployeeAgency Publisher中的外键,例如agency_idpublisher_id

6 个答案:

答案 0 :(得分:1)

最佳做法可能是引入雇主类。

另一方面,将员工分为AgencyEmployee和PublisherEmployee将是一件坏事。

如果介绍雇主是不可能的,我会在雇员中指明雇主类型(代理商或发布商)。

对更新后问题的回复:

这是一个选项,但雇主类型更好,因为:

  1. 您可能希望将来添加其他雇主类型
  2. Employees表的每一行都有一个空字段。

答案 1 :(得分:0)

这样的声音可以建模为ternary relationship。看看您是否喜欢本MSDN文章中采用的方法。

答案 2 :(得分:0)

我个人的偏好是有一张你明确假设不能使用的表格(代理商和出版商的SuperType;雇主)

一个简单的替代方法是简单地不强制执行外键约束。如果对数据结构的所有修改都是通过您控制的存储过程完成的,那么这不一定是有问题的。

我的最终偏好与您的建议相似,即为AgencyEmployees提供一个表,为PublisherEmployees提供一个表。但是我会把它分开一步......

Table1: Agency              (id, name, etc)
Table2: Publisher           (id, name, etc)
Table3: Employee            (id, name, etc)
Table4: AgencyEmployees     (agency_id, employee_id)
Table5: PublisherEmployees  (publisher_id, employee_id)


我这样做的一个原因是让这个时间依赖变得微不足道。员工在公司之间开始,离开和走动。以下对上述内容的略微修改将允许您跟踪...

Table1: Agency              (id, name, etc)
Table2: Publisher           (id, name, etc)
Table3: Employee            (id, name, etc)
Table4: AgencyEmployees     (agency_id,    employee_id, start_date, leave_date)
Table5: PublisherEmployees  (publisher_id, employee_id, start_date, leave_date)

这在任何时候都不会强制每位员工雇用1名雇主,但这可以通过您的存储过程,GUI等强制执行......

答案 3 :(得分:0)

我使用过这种方法:

Employee.EmployerType('AGENCY'或'PUBLISHER')

Employee.EmployerID(AgencyID或PublisherID)

它工作正常,但你需要在很多SQL中使用case语句。如果你使用的是ORM,你就失去了FK的关系。

我将大部分代码移动到n:m关系,以便我可以利用我们的ORMs FK支持。

答案 4 :(得分:0)

显然,雇主实体是首选,但除此之外......

拥有AgencyEmployee& PublisherEmployee表意味着很难确定员工是属于某个类别还是其他类别。

所以我会在Employees表中添加和EmployerType列;它为后续的SQL查询增加了一些额外的复杂性,但它在您给出的约束条件下工作。

出于兴趣,为什么你能够添加AgencyEmployee& PublisherEmployee表,但不添加Employer表?好奇......

答案 5 :(得分:0)

CanBerkGüder的+1。

从技术上讲,引入雇主超类型意味着您引入雇主关系,其中包含代理商和发布商共有的所有属性,代理商特定(不确定如何调用)与雇主关键字以及所有特定于代理商的属性和雇主关键字的关系作为外键,然后代理商作为查询或视图,只与代理商加入AgencySpecific,同样适用于发布商。

将代理商和发布商数据分散到您必须每次加入的两个表中可能有点麻烦,但另一种方法是将大部分与员工相关的查询写入两次,一次使用代理商,一次使用Publisher,然后手工制作他们的工会以结合结果。 (我没有看到一个查询构建器可以帮助解决这类基本问题。)我必须为使用“无超类型”方法的项目执行此操作,我不想再这样做。

如果你问我,BTW三元关系甚至是n对n关系都不是好的设计实践。仅使用功能(即1对1和1对1),例如约束变得更容易制定。