【问题标题】:Database Architecture Many-to-Many-to-Many数据库架构多对多对多
【发布时间】:2014-01-23 19:45:48
【问题描述】:

我遇到了如何更改数据库模型的问题:

现在我们已经预定义了表Categories 假设表 PlacesPeople 可以分配给类别,所以看起来像这样:

People <=> PeopleCategories <=> Categories <=> PlaceCategories <=> Places

(人可以有很多类别,类别可以有很多人,地方可以有很多类别,类别可以有很多地方)

但现在有一个新的要求:

在个人资料上根据类别显示所有相应的地方(到目前为止没问题)并添加一个对某些属性建模的复选框(例如在前端显示为最喜欢的地方)。地点个人资料的另一侧相同,用复选框标记分配到至少一个相同类别的人员。

我想知道是否有一些很好的方法来对此进行建模 - 我唯一想到的是添加一个新的 PeoplePlaces 表,但是我必须手动控制人员或地点是否没有改变他们的类别并且他们仍然被分配等等 - 我必须在应用层管理的数据的一致性会有很大的问题。

我可能做的第二件事是完全删除类别并仅在PeoplePlaces 级别设置它,但我会为用户失去一些简单性:用户可以选择大约 10 个预定义类别,因此人员和地点之间的链接在前端是非常自动的,只有管理员应该看到哪些地方分配给了哪些人并管理我正在谈论的那个复选框

您对这种架构有何建议?提前致谢! (如果它对某种解决方案很重要,那么它是一个 MySQL 数据库,但这更像是一种通用架构)

【问题讨论】:

  • 这和 DBA.SE 的这个问题类似:Are there DBMS that allow a Foreign Key that References a View (and not only base tables)? 请阅读所有答案和 cmets 中的讨论,实现起来并非易事。
  • @ypercube:是的,这正是我所面临的,我看到你提出了这个问题。你最后用了什么?我可能会尝试约束解决方案,因为我的表可能不会经常更改。谢谢你的链接!
  • 这对我来说更像是一个理论问题,而不是一个实际问题。对于 MySQL,我想我会使用约束解决方案(它还需要对 PeopleCategoriesPlaceCategories 表使用 DELETE 触发器,或者使用其他方式来自定义这两个表上的 DELETE 操作。)

标签: mysql database database-design architecture data-modeling


【解决方案1】:

我认为删除类别不是一个好主意。

您正在做的是引入一个新实体 - PersonsFavouritePlaces - 它直接关联人物和地点,而不是通过类别。将 PersonsFavouritePlace 限制为由 Category 链接的 Person 和 Place 是明智的,因此它可能应该引用 PeopleCategories 和 PlaceCategories 而不是 People 和 Category 表。

表格如下所示:

create table PeopleFavourtiePlace
(
  ID int not null, -- Primary key
  PeopleCategoriesId int not null, -- FK to PK of PerpleCategories
  PlaceCategoriesId int not null -- FK to PK of PlaceCategories
)

我不知道 MySql 是否支持级联删除,但如果是这样,两个 FK 应该打开它,所以当有人取消选择一个类别(删除 PeopleCategories 行)时,如果它链接到该类别中最喜欢的地方,它也会得到已删除。

但是,如果一个人通过多个类别链接到一个地方,那么它就会变得复杂......

【讨论】:

  • 这太简单了。它允许在此表中添加行,将 Person 与没有连接它们的 Category 的 Place 相关联。
【解决方案2】:

如果我对您的问题的理解正确,您需要确保一个人只能偏爱与该人属于同一类别的地点?

如果是这样,请查看以下模型:

我们不直接链接“端点”,而是“链接链接”。这允许我们将 PERSON_CATEGORY.CATEGORY_ID 和 PLACE_CATEGORY.CATEGORY_ID 迁移到 FAVORED_PLACE 表中,并在那里“合并”它们,生成一个 FAVORED_PLACE.CATEGORY_ID 字段(请注意上图中的FK1,FK2)。

因此,如果一个人与一个地方有关,那必须通过一个共同的类别来完成。

此外,由于 CATEGORY_ID 在 PERSON_CATEGORY 的 PK 之外,因此人员和地点的特定组合只能使用一次,即使它们通过多个类别匹配。实际上,您选择了一个常见类别作为“特殊”类别。如果一个地方(或人)从特殊类别中删除,您需要选择另一个常见类别作为特殊类别。如果没有剩余的常用类别,FAVORED_PLACE 中的对应行将不再允许存在。

【讨论】:

  • 我真的很喜欢这个模型,但据我所知,应用层仍有一些逻辑 - 如果一个人取消设置某个类别,我可以填充级联删除但并不总是因为它们可以链接按其他类别 - 这是应用程序必须检查的内容(或者触发器可以解决这个问题,但我现在不允许使用它们)。我对吗?感谢您的回答!
  • 不一定要在应用层。您可以编写一个 DELETE 过程(用于Person_Category 表,另一个用于另一个表)来处理该问题。然后让您的应用程序只执行删除调用这些过程。
  • @kuncajs 如果你想移动到不同的“特殊”类别,那么是的,涉及一些特殊的逻辑(否则你可以只删除级联)。如果由于某种原因您无法将该逻辑封装在触发器中,您仍然可以以一种易于重用的方式封装它(正如 ypercube 所建议的那样)。
  • @kuncajs 然而,pure 触发解决方案(CATEGORY_ID 上没有 FK)很容易导致竞争条件:事务 T1 从类别中删除人员,但 T2 连接该人员并地点(因为它认为他们仍然有共同的类别,因为 T1 还没有提交)。您必须使用锁定来避免这种情况,这很容易出错。如果您有 FK,DBMS 本身会确保引用完整性不会被破坏。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-08
  • 2022-01-15
  • 1970-01-01
相关资源
最近更新 更多