关系数据库:以不同的解释重用相同的 table
Relational Database: Reusing the same table in a different interpretation
问题描述
我目前正在从事一个需要关系数据库进行存储的项目。
在思考了一会儿数据及其关系后,我 运行 陷入了一个相当重复的问题:
我遇到了实体 A 的通用数据模式,其中包含一些字段,例如名称、描述、值。该实体与实体 B 有多重 n-1 关系。所以实体 B 在关系 rel1 中有 n 个实体 A,在关系 rel2 中有 n 个实体 A。
现在我试图将这个数据模型分解为关系数据库的模式(例如 Postgres,MySQL)。
经过一些研究,我还没有真正找到针对这个特定问题的“最佳”解决方案。
目前发现的一些类似问题:
- Whosebug
- DBA Stackexchange
我的想法
所以我考虑了可能的解决方案,我将在这里展示:
1。重复 table
实体B与实体A的关系是有一定意义的。因此可以创建多个 table(每个关系 1 个)。这将解决所有紧迫的问题,但本质上会重复 tables,这意味着现在必须将更改反映到多个 tables(例如新列)。
2。引入类型栏目
我可以说“实体 B 与 n 个实体 A 相关联”,而不是多重关系。此外,我会添加一个类型列,然后告诉我 A 属于哪个关系实体。我不确定这是如何用像 Spring-Hibernate 这样的常见 ORM 表示的,如果这会引入我目前不知道的其他问题。
3。抽象出实体A的共同属性
另一种选择是创建一个 ADetails 实体,它捆绑了实体 A 的所有属性。
然后我将创建两个实体来表示每个关系,并以一对一的关系连接到 ADetails 实体。这将解决外键的解释问题,但可能开销太大。
我的问题
- 在大中型项目的背景下,这些解决方案是否可行?
- 是否存在排除一种特定方法的某些缺点?
- 还有其他(更好的)选择我没有考虑过吗?
我很感激在这件事上的任何帮助。
编辑 1 - PPR(人-党-角色)
感谢AntC 的建议。 PPR Description
我觉得描述的情况符合我的问题。
让我们分解一下:
实体B是一个事件。对于给定的参与者,只有一个事件可以使这更容易。所以从事件到参与者的关系是1-n。
实体 A 可以描述为组、人员、组织,但考虑到我的情况,它们都具有相同的属性。因此,将它们分成单独的 table 感觉是个错误的想法。
用class图说明情况:
事件(实体 B)具有 n 个组(实体 A)、n 个人员(实体 A)和 n 个组织(实体 A)的集合。
如果我理解正确的话,建议如下:
- 在我的例子中,事件和参与者之间的关系是 1-n
- RefRoles table 代表描述参与者所属关系的 ParticipantType 列(例如,它是客户还是事件服务的一部分)
- 因为我所有的组、人员和组织都具有相同的属性,此时唯一需要的 table 是参与者 table
- 如果将来有单独的属性,我会引入一个新的 table(例如人),它在 1-1 关系中引用参与者。
- 如果要添加多个table,则多个1-1关系的外键互斥(所以一个参与者只能有一个Group/Person/Organization)
AntC 和 Christian Beikov 建议的解决方案
拆分 table 确实有意义,同时将共同属性保留在一个 table 中。
目前没有单独的属性,但不再需要类型列,因为可以使用外键查看实体属于哪个关系。
我为此创建了一个小示例:
- 一个事件存在 3 种类型(以前的类型列)的人员:工作人员、VIP、访客
- 公共属性以 1-1 关系映射到此人 table。
- 为简单起见:每个人(工作人员、贵宾、访客)只能参加一个活动。 (在更高级的示例中将是 n-m 关系)
数据库模式如下:
在我看来,这种方法比类型列要好。
它还解决了以后必须在应用程序中根据其类型解释实体的问题。也可以解析 ORM 中的类型列 ,但如果您使用的 ORM 不支持解析它,这种方法可以避免麻烦。
IMO 因为您已经为这些对象使用了专用术语,所以它们可能会发生分歧,之后拆分 table 需要大量工作,在代码方面也是如此,所以我建议您映射专用 entities/tables从头开始。
问题描述
我目前正在从事一个需要关系数据库进行存储的项目。 在思考了一会儿数据及其关系后,我 运行 陷入了一个相当重复的问题:
我遇到了实体 A 的通用数据模式,其中包含一些字段,例如名称、描述、值。该实体与实体 B 有多重 n-1 关系。所以实体 B 在关系 rel1 中有 n 个实体 A,在关系 rel2 中有 n 个实体 A。
现在我试图将这个数据模型分解为关系数据库的模式(例如 Postgres,MySQL)。 经过一些研究,我还没有真正找到针对这个特定问题的“最佳”解决方案。
目前发现的一些类似问题:
- Whosebug
- DBA Stackexchange
我的想法
所以我考虑了可能的解决方案,我将在这里展示:
1。重复 table
实体B与实体A的关系是有一定意义的。因此可以创建多个 table(每个关系 1 个)。这将解决所有紧迫的问题,但本质上会重复 tables,这意味着现在必须将更改反映到多个 tables(例如新列)。
2。引入类型栏目
我可以说“实体 B 与 n 个实体 A 相关联”,而不是多重关系。此外,我会添加一个类型列,然后告诉我 A 属于哪个关系实体。我不确定这是如何用像 Spring-Hibernate 这样的常见 ORM 表示的,如果这会引入我目前不知道的其他问题。
3。抽象出实体A的共同属性
另一种选择是创建一个 ADetails 实体,它捆绑了实体 A 的所有属性。 然后我将创建两个实体来表示每个关系,并以一对一的关系连接到 ADetails 实体。这将解决外键的解释问题,但可能开销太大。
我的问题
- 在大中型项目的背景下,这些解决方案是否可行?
- 是否存在排除一种特定方法的某些缺点?
- 还有其他(更好的)选择我没有考虑过吗?
我很感激在这件事上的任何帮助。
编辑 1 - PPR(人-党-角色)
感谢AntC 的建议。 PPR Description
我觉得描述的情况符合我的问题。 让我们分解一下:
实体B是一个事件。对于给定的参与者,只有一个事件可以使这更容易。所以从事件到参与者的关系是1-n。
实体 A 可以描述为组、人员、组织,但考虑到我的情况,它们都具有相同的属性。因此,将它们分成单独的 table 感觉是个错误的想法。
用class图说明情况: 事件(实体 B)具有 n 个组(实体 A)、n 个人员(实体 A)和 n 个组织(实体 A)的集合。
如果我理解正确的话,建议如下:
- 在我的例子中,事件和参与者之间的关系是 1-n
- RefRoles table 代表描述参与者所属关系的 ParticipantType 列(例如,它是客户还是事件服务的一部分)
- 因为我所有的组、人员和组织都具有相同的属性,此时唯一需要的 table 是参与者 table
- 如果将来有单独的属性,我会引入一个新的 table(例如人),它在 1-1 关系中引用参与者。
- 如果要添加多个table,则多个1-1关系的外键互斥(所以一个参与者只能有一个Group/Person/Organization)
AntC 和 Christian Beikov 建议的解决方案
拆分 table 确实有意义,同时将共同属性保留在一个 table 中。 目前没有单独的属性,但不再需要类型列,因为可以使用外键查看实体属于哪个关系。
我为此创建了一个小示例:
- 一个事件存在 3 种类型(以前的类型列)的人员:工作人员、VIP、访客
- 公共属性以 1-1 关系映射到此人 table。
- 为简单起见:每个人(工作人员、贵宾、访客)只能参加一个活动。 (在更高级的示例中将是 n-m 关系)
数据库模式如下:
在我看来,这种方法比类型列要好。
它还解决了以后必须在应用程序中根据其类型解释实体的问题。也可以解析 ORM 中的类型列
IMO 因为您已经为这些对象使用了专用术语,所以它们可能会发生分歧,之后拆分 table 需要大量工作,在代码方面也是如此,所以我建议您映射专用 entities/tables从头开始。