【问题标题】:Storing and querying undirected many-to-many relationships存储和查询无向多对多关系
【发布时间】:2014-03-30 21:02:56
【问题描述】:

我遇到了一个包含以下关系的数据库模式:

人(ID,姓名) 朋友(ID1,ID2)

ID1 和 ID2 是 Person.ID 的外键

朋友是一种无向关系(即它是双向的)。在模式中,对于从 ID 123 到 ID 456 的给定友谊,它存储为两个元组:(123, 456) 和 (456, 123)。

在我看来,将单个概念实体存储在两个元组中并不好:数据可能会变得不一致;并且数据集中存在重复。

除非我弄错了,我们应该可以对数据库做任何我们想做的事情,即使只有一个元组。在最坏的情况下,可以轻松地重新创建表的版本:

SELECT *
FROM Friend
UNION
SELECT ID2 as ID1, ID1 as ID2
FROM Friend

所以我的问题是:存储无向多对多关系的最佳做法是什么?为什么?

如果将信息存储在两个元组中是最好的处理方式,那么 INSERT INTO、UPDATE 和 DELETE 查询是更改两条记录,还是依靠触发器来保持一致性更好?

【问题讨论】:

  • 这里不需要存储两个元组。你可以通过只存储一个关系来做你想做的一切。您必须修改查询以检查两个方向,仅此而已。

标签: sql database


【解决方案1】:

嗯,在大多数数据库中,我可能会在以下两个条件下为 Friends 表选择一行:

  • id1、id2 上的唯一索引
  • 检查 id1 的约束

但是,在 MySQL 中,您无法实现检查约束。因为您必须求助于触发器,所以您不妨使用管理重复行的插入/更新/删除触发器。

这两种方法各有利弊。例如,首先,您需要注意插入值的顺序。或者,您需要一个触发器。或者,无论如何我通常会做的是有一个存储过程来包装数据库更改并处理正确的插入顺序。而且,获取 X 的所有朋友需要更复杂的查询。

第二种方法使用更多空间,这可能很麻烦。但是,它更容易回答诸如“谁是你朋友的朋友”之类的问题。但是插入和更新的开销更大。

最后,这实际上取决于您要运行什么样的查询。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-08
    • 2019-05-18
    • 1970-01-01
    • 1970-01-01
    • 2020-08-02
    • 2014-09-03
    • 2022-01-15
    • 1970-01-01
    相关资源
    最近更新 更多