在具有两条关联路径的数据库结构中保持数据完整性

Preserve data integrity in a database structure with two paths of association

我有这种情况,既简单又烦人。

要求是

  1. 每个 item 必须有一个关联的 category

  2. item 可以 包含在 set.

  3. Sets必须由相同的category.items组成。

  4. 同一类别可能有多个sets

插入新数据所需的逻辑过程如下:

  1. Categories被插入。

  2. Items 被插入。对于每个新的 item,分配一个 category

  3. Sets 共创建了 items 个相同的 category

我想要一个确保表之间数据完整性的设计。

我想出了以下设计,但我不知道如何保持数据完整性。

如果不考虑以黄色突出显示的关系,一切都非常简单,数据完整性是设计强制的:一个项目只有在分配给一个集合时才获得一个类别,并且类别由集合给出itself.However,不可能有不与集合相关联但与类别相关联的项目,这很烦人。

我想避免使用特殊的“桥接集”来为项目分配类别,因为这会让人觉得很笨拙,而且无法区分真实集和特殊集。

所以我介绍了黄色的关系。但现在您可以创建不同类别的对象集!

如何在 MySQL 中仅使用普通约束(索引、唯一性、FK)来避免此完整性问题?

我也想避免使用触发器,因为我不喜欢它们,因为它似乎是解决此问题的一种脆弱且不太可靠的方法...

我读过 之类的类似问题,但我不明白如何在我的案例中应用该解决方案...

有趣的场景。我没有看到 slam-dunk 'best' 方法。这里的一个考虑因素是:items 中有多少比例在 sets 中与仅附加到 categories 中?

  • 您不想要的是 items 上的两个字段。因为,正如您所说,将会出现数据异常:item 的直接 category 不同于它通过 set.[=33= 继承的 category ]

  • 理想情况下,您会在 items 上创建一个字段,该字段是一种代数数据类型,又名 Tagged Union,并带有一个标签,说明其有效负载是 category对比 set。但是 SQL 不支持 ADT。所以任何 SQL 方法都必须有点老套。

  • 然后我建议折衷方案是使每个 item 成为 set 的成员,并从中继承其 category。那么数据访问是一致的:总是JOINitems-sets-categories.

  • 为了支持这一点,创建虚拟 sets 其唯一目的是 link 到 category.

  • 为了解决“无法区分真实集合和特殊集合”的问题:在sets上添加一个额外的field/indicator:这是一个'real'设置 vs 这是一个 link-to-category 设置。 (或者黑客:将 set-description 设为“类别:”。)

添加: 顺便说一句,您的“插入新数据所需的逻辑过程”是错误的:您必须在 items 之前插入 sets(第 3 步) (第 2 步)。

我想我可能会通过查看 Roger Wolf 对类似情况的回答找到解决方案:

本质上,在 items table 中,我已将 set_id FK 更改为复合 FK,同时引用 set.idset.category_id 来自,分别为 items.set_iditem.category_id 列。

这样在itemstable上两个FK就有了重叠。 因此,对于 items table 中的每一行,一旦选择了 category_id,引用 sets table 的 FK 将被迫指向一组同一类别。 如果不遵守此条件,则会抛出异常。

现在,最初的答案附带了反对使用这种方法的建议。 我不确定这是否是个好主意。 它当然有效,而且我认为与使用 tiggers 进行如此简单的更复杂设计的解决方案相比,这是一个相当优雅的解决方案。 如果大量应用到大量 table 中,相同的解决方案可能更难理解和维护。

编辑: 正如 AntC 在下面的评论中指出的那样,这种技术虽然有效,但会带来潜在的问题,例如如果您想将 category_id 更改为 set。 在这种情况下,您必须更新链接到 set 的每个 itemcategory_id。 这需要 BEGIN COMMIT/END COMMIT 环绕更新。

所以最终可能不值得,最好进一步调查需求以找到更好的架构。