创建“多对多”关系的常用方法是啥?
Posted
技术标签:
【中文标题】创建“多对多”关系的常用方法是啥?【英文标题】:What is the common way to create "Many-To-Many" relationships?创建“多对多”关系的常用方法是什么? 【发布时间】:2011-12-01 11:17:29 【问题描述】:我有 2 个表 Product
包含商店的产品,ProductStatus
表示产品是新的、已售出等。一种产品可能有多种状态。
我需要关联产品和状态。我想了两个办法:
-
添加第三个表
ProductToStatus
将匹配 ProductId 与 ProductStatusId
将Status
列添加到Product
表中,该表将包含用逗号分隔的状态ID ("4,12,34,");
上述每个解决方案的优缺点是什么,或者可能有另一种常见的方法来做到这一点?
【问题讨论】:
永远永远永远永远,即使是在周日、银行假日,或者在激情或浪漫的醉酒之夜之后,永远,为了小圆桌,请使用逗号分隔的字符串数据库字段中的值:) 【参考方案1】:第一种方法是正确的,并且更常见。用于建模多对多关系的表称为连接表、关系表或联结表等。
与您提出的第二种方式相比,它的主要优点是:
更快的数据库操作 - 例如,如果您想查找所有具有特定状态的产品,使用连接表的查询将非常快并创建正确的索引,而您建议的第二种方式意味着搜索给定的子字符串每个产品(会很慢)。 约束检查 - 您可以将ProductId
和ProductStatusId
列声明为外键,数据库将阻止您为产品分配不存在状态。
连接表的主要缺点是添加/修改产品的代码可能有点难以编写,因为您需要操作更多的数据库记录。幸运的是,现代 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!
【讨论】:
以上是关于创建“多对多”关系的常用方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章