在具有两条关联路径的数据库结构中保持数据完整性
Preserve data integrity in a database structure with two paths of association
我有这种情况,既简单又烦人。
要求是
每个 item
必须有一个关联的 category
。
每 item
可以 包含在 set
.
中
Sets
必须由相同的category
.items
组成。
同一类别可能有多个sets
。
插入新数据所需的逻辑过程如下:
Categories
被插入。
Items
被插入。对于每个新的 item
,分配一个 category
。
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
。那么数据访问是一致的:总是JOIN
items-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.id
和 set.category_id
来自,分别为 items.set_id
和 item.category_id
列。
这样在items
table上两个FK就有了重叠。
因此,对于 items
table 中的每一行,一旦选择了 category_id
,引用 sets
table 的 FK 将被迫指向一组同一类别。
如果不遵守此条件,则会抛出异常。
现在,最初的答案附带了反对使用这种方法的建议。
我不确定这是否是个好主意。
它当然有效,而且我认为与使用 tiggers 进行如此简单的更复杂设计的解决方案相比,这是一个相当优雅的解决方案。
如果大量应用到大量 table 中,相同的解决方案可能更难理解和维护。
编辑:
正如 AntC 在下面的评论中指出的那样,这种技术虽然有效,但会带来潜在的问题,例如如果您想将 category_id
更改为 set
。
在这种情况下,您必须更新链接到 set
的每个 item
的 category_id
。
这需要 BEGIN COMMIT/END COMMIT 环绕更新。
所以最终可能不值得,最好进一步调查需求以找到更好的架构。
我有这种情况,既简单又烦人。
要求是
每个
item
必须有一个关联的category
。每
中item
可以 包含在set
.Sets
必须由相同的category
.items
组成。同一类别可能有多个
sets
。
插入新数据所需的逻辑过程如下:
Categories
被插入。Items
被插入。对于每个新的item
,分配一个category
。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
。那么数据访问是一致的:总是JOIN
items-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.id
和 set.category_id
来自,分别为 items.set_id
和 item.category_id
列。
这样在items
table上两个FK就有了重叠。
因此,对于 items
table 中的每一行,一旦选择了 category_id
,引用 sets
table 的 FK 将被迫指向一组同一类别。
如果不遵守此条件,则会抛出异常。
现在,最初的答案附带了反对使用这种方法的建议。 我不确定这是否是个好主意。 它当然有效,而且我认为与使用 tiggers 进行如此简单的更复杂设计的解决方案相比,这是一个相当优雅的解决方案。 如果大量应用到大量 table 中,相同的解决方案可能更难理解和维护。
编辑:
正如 AntC 在下面的评论中指出的那样,这种技术虽然有效,但会带来潜在的问题,例如如果您想将 category_id
更改为 set
。
在这种情况下,您必须更新链接到 set
的每个 item
的 category_id
。
这需要 BEGIN COMMIT/END COMMIT 环绕更新。
所以最终可能不值得,最好进一步调查需求以找到更好的架构。