“一对多”建模问题

4
什么是最佳建模方式...
假设我有两个对象:AgencyPublisher,它们都与Employee存在1对n的关系。这是真正的1对n关系,因为每个Employee只能为一个Agency或一个Publisher工作。进一步假设我不能引入超类型(例如Employer),以保存1对n关系。
我的首选解决方案是在Employee中有一个外键,可以链接到AgencyPublisher的主键(我的所有主键都是64位ID,在整个数据库中是唯一的)。但是,现在我将无法映射双向关联,除非在Employee中指示这是Agency还是Publisher关系。
我另一个选择是使用两个表AgencyEmployeePublisherEmployee,然后将它们作为传统的1对n双向关联连接起来。
在这种情况下,您认为哪种方式是最佳实践?
更新:感谢在如此短的时间内提供了如此出色的回复!您认为以下解决方案如何:在Employee中为AgencyPublisher分别设置外键,例如agency_idpublisher_id
6个回答

1

最佳实践可能是引入一个雇主类。

另一方面,将员工分为代理员工和发布员工将是不好的做法™。

如果引入雇主是不可能的,我会在员工中指示雇主类型(代理或发布)。

对更新问题的回应:

那是一个选择,但employer_type更好,因为:

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

我同意最佳实践和Bad Thing调用,但我认为从规范化的角度来看,使用第三个表,以EmployeeID作为主键,包含EmployerID和EmployerType会更好。 - Harper Shelby
@Harper:没错,但从实用的角度来看,这意味着另一个连接(和一个多列主键)。 - Can Berk Güder

0

我的个人偏好是有一个明确不能使用的表(代理商和出版商的超类型;雇主)

一个简单的替代方案是不强制执行外键约束。只要所有对数据结构的修改都通过您控制的存储过程完成,这并不一定会有问题。

我的最终偏好与您的建议类似,即为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)

这并不强制要求每个员工在任何时候只能有一个雇主,但可以通过您的存储过程、GUI等来实施。


0

听起来这个问题可以建模为一个三元关系。请看看这篇MSDN文章中采用的方法是否适合你。


0
我使用了这种方法:
Employee.EmployerType('AGENCY'或'PUBLISHER')
Employee.EmployerID(AgencyID或PublisherID)
这个方法还行,但需要在很多 SQL 中加上 case 语句。并且如果你使用 ORM,就会失去外键关系。
所以我正在将大部分的代码迁移到 n:m 关系,以便利用我们的 ORM 外键支持。

0

显然,雇主实体会更好,但如果没有的话...

拥有AgencyEmployee和PublisherEmployee表意味着很难确定员工属于哪一类。

因此,我会在Employees表中添加一个EmployerType列;这会在后续的SQL查询中增加一些复杂性,但它可以在您给出的限制条件下工作。

顺便问一下,为什么您能够添加AgencyEmployee和PublisherEmployee表,却不能添加一个Employer表呢?只是好奇...


0

A +1 给 Can Berk Güder。

从技术上讲,引入雇主超类型意味着您引入了一个雇主关系,该雇主关系具有所有代理和出版商的公共属性、一个 AgencySpecific(不确定如何称呼它)关系与 Employer 键和所有代理特定属性以及雇主键作为外键,然后 Agency 作为查询或视图,仅将 AgencySpecific 与 Employer 进行连接,并对出版商进行同样的操作。

可能在两个表中分别拥有代理和出版商数据并且每次都要进行连接会有点麻烦,但另一种选择是将与员工相关的大多数查询写两次,一次使用代理,一次使用出版商,然后手工制定它们的联合以组合结果。(我没有看到任何查询构建器能够帮助处理这些基本问题。)我曾经在一个使用“无超类型”方法的项目中这样做过,我不想再做一次。

顺便说一句,如果您问我,三元关系甚至 n 对 n 关系都不是很好的设计实践。仅使用函数(即 1 对 n 和 1 对 1)例如约束条件变得更加容易。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接