创建“多对多”关系的常用方法是啥?

Posted

技术标签:

【中文标题】创建“多对多”关系的常用方法是啥?【英文标题】:What is the common way to create "Many-To-Many" relationships?创建“多对多”关系的常用方法是什么? 【发布时间】:2011-12-01 11:17:29 【问题描述】:

我有 2 个表 Product 包含商店的产品,ProductStatus 表示产品是新的、已售出等。一种产品可能有多种状态。

我需要关联产品和状态。我想了两个办法:

    添加第三个表 ProductToStatus 将匹配 ProductIdProductStatusIdStatus 列添加到Product 表中,该表将包含用逗号分隔的状态ID ("4,12,34,");

上述每个解决方案的优缺点是什么,或者可能有另一种常见的方法来做到这一点?

【问题讨论】:

永远永远永远永远,即使是在周日、银行假日,或者在激情或浪漫的醉酒之夜之后,永远,为了小圆桌,请使用逗号分隔的字符串数据库字段中的值:) 【参考方案1】:

第一种方法是正确的,并且更常见。用于建模多对多关系的表称为连接表、关系表或联结表等。

与您提出的第二种方式相比,它的主要优点是:

更快的数据库操作 - 例如,如果您想查找所有具有特定状态的产品,使用连接表的查询将非常快并创建正确的索引,而您建议的第二种方式意味着搜索给定的子字符串每个产品(会很慢)。 约束检查 - 您可以将ProductIdProductStatusId 列声明为外键,数据库将阻止您为产品分配不存在状态。

连接表的主要缺点是添加/修改产品的代码可能有点难以编写,因为您需要操作更多的数据库记录。幸运的是,现代 ORM 框架负责幕后的所有工作。

【讨论】:

“幸运的是,现代 ORM 框架处理了所有幕后工作” ...但是 do they play nice with the compound keys 自然出现在关系表中? @onedaywhen Hibernate 和 GORM(基于 Hibernate)为连接表创建适当的复合键。【参考方案2】:

到目前为止,选项 1 更好且最常用,因为您可以使用两个表的外键设置链接表 (ProductToStatus),这将保持数据完整性。

【讨论】:

【参考方案3】:

第二种方法听起来相当笨拙。您将如何对此类模型执行查询? 第一种方法是正确的,这是人们通常的建模方式。

【讨论】:

【参考方案4】:

为了模型,应使用备选方案 1。备选方案 2 是一个丑陋的解决方法。

如果您使用替代方案 2,您甚至无法进行 FK。

【讨论】:

【参考方案5】:

选项 2 的问题是您的新数据结构与 SQL 的运算符不兼容。例如,"4,12,34," 的值应该被认为与"4,34,12," 相同:在不能重载 SQL 运算符的情况下,您需要 a) 编写用户定义的函数 b) 训练用户使用 UDF 而不是SQL 运算符。对每个运算符重复。

这同样适用于约束。例如,您需要阻止值"4,12,4,",因为它包含重复的成员。同样,您需要滚动自己的约束,大概使用 SQL CHECK 约束。

在编写这些运算符和约束的过程中,您总是需要拆分成员,对它们进行运算符,然后再次连接它们。这就引出了一个问题:为什么不把它们分开呢?然后我们回到选项 1!

【讨论】:

以上是关于创建“多对多”关系的常用方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

在 Django 中建模异构多对多关系的最佳方法是啥?

思考具有两个外键的一对多或多对多关系的正确方法是啥?

在 NHibernate 中定义多对多关系以允许删除但避免重复记录的正确方法是啥

Django多对多关系建立及Form组件

这是在fuelphp中与额外字段创建多对多关系的正确方法吗

参数,查找方法,多对多的操作