我应该如何建模“要么/要么”关系?

假设我有一个名为Software的实体,以及两个子类型FreeSoftware和NonFreeSoftware。NonFreeSoftware实体具有购买日期、供应商等属性。FreeSoftware实体具有许可证、源代码URL等属性。 那么,如果我想建模另一个实体OperatingSystem,应该如何做呢?它与Software存在“是一个”关系,但与FreeSoftware和NonFreeSoftware存在“要么/要么”关系。 我觉得在分析这个层次结构时可能有些遗漏。

请查看这个答案。它详细介绍了如何在数据库中建模这种关系的实现细节。 - Nick Chammas
2个回答

这样管理的方法是,子类型必须由超类型确定(即子类型的主键也是从子类型到超类型的外键)。 挑战在于理解某个事物是否真正互斥。子类型的属性应仅适用于那些子类型,但很可能有一些子类型是互斥的,而另一些则不是。 如果你有一些互斥的子类型,那么可以在超类型上使用一个分区属性来指示哪些互斥的子类型适用(两个或更多个)。可以使用约束或触发器来强制实施互斥关系。 如果你有非互斥的子类型,则它们可以存在而不使用任何分区属性。 考虑这个数据模型:

ERD

你有三种超级类型,但是FREE_SOFTWARENON-FREE_SOFTWARE类型是互斥的,基于SOFTWARE.free_not_free标志分区属性。任何给定的软件也可能是一个OPERATING_SYSTEM,无论它是否免费。

1略微离题:你用什么工具制作这个实体关系图? - Daniel Serodio
@DanielSerodio - 我使用了自己基于James Martin ERD符号的智能形状来制作Visio图。这些形状使用了自定义线条纹理,使它们看起来更加随意,这样可以提醒人们这个图表是一个“草图”或者初步设计。 - Joel Brown
@JoelBrown 你愿意分享你的模板吗?这些形状真的很漂亮。 - imoatama
3@imoatama - 好久不见了,但我终于抽出时间在这里发布了模板:https://moosewarevisioerd.codeplex.com/ 请注意,正如描述中所述,该模板的智能形状是为较旧版本的Visio构建的,一些关系连接器形状的行为可能有些不稳定。总有一天我会找时间来修复它们。 - Joel Brown

为什么操作系统会成为一个全新的实体?它应该属于软件类别,因为它就是软件。如果操作系统是闭源的,那么它应该有购买日期、供应商等信息。而开源操作系统则应该有许可证、源代码URL等。 我建议与"SoftwareType"或类似的关系进行关联。这样你就可以明确指定软件是操作系统、应用程序还是其他类型的软件。

我希望将OperatingSystem作为一个独立的实体,因为它是软件的一种专业化。它可能具有其他软件所没有的属性(例如内核类型、实时操作系统标志、多用户标志等)。 - jl6
1@jl6 我还是持不同意见。每个软件(无论是操作系统还是其他)都会有特定的属性。这些属性可以存储在其他地方。将操作系统与其他软件分开,会减少可扩展性。 - Thomas Stringer
如果我理解正确,您正在推荐一个软件实体和软件类型实体。您是说免费、非免费和操作系统都只是软件类型的不同实例吗?我相信您是正确的,但是那么不同类型的属性存储在哪里呢? - jl6