Sql 多对多关系:在列中使用关联表或分隔值?

Sql 多对多关系:在列中使用关联表或分隔值?,sql,database,database-design,architecture,many-to-many,Sql,Database,Database Design,Architecture,Many To Many,更新2009.04.24 我的问题的重点不是开发人员的困惑以及如何应对 关键是要理解分隔值何时是正确的解决方案 我见过商业产品数据库(Ektron lol)中使用的分隔数据 SQL Server甚至有一个XML数据类型,因此可以用于与分隔字段相同的目的 /end Update 我正在设计的应用程序有一些多对多关系。在过去,我经常使用关联表在数据库中表示这些。这给开发者带来了一些困惑 下面是一个示例数据库结构: Document --------------- ID (PK) Title Cate

更新2009.04.24

我的问题的重点不是开发人员的困惑以及如何应对

关键是要理解分隔值何时是正确的解决方案

我见过商业产品数据库(Ektron lol)中使用的分隔数据

SQL Server甚至有一个XML数据类型,因此可以用于与分隔字段相同的目的

/end Update

我正在设计的应用程序有一些多对多关系。在过去,我经常使用关联表在数据库中表示这些。这给开发者带来了一些困惑

下面是一个示例数据库结构:

Document
---------------
ID (PK)
Title
CategoryIDs (varchar(4000))


Category
------------
ID (PK)
Title
文档和类别之间存在多对多关系。

在此实现中,Document.categoryId是一个大管道分隔的CategoryId列表

对我来说,这是不好的,因为它需要在查询中使用子字符串匹配,而查询不能使用索引。我认为这将是缓慢的,不会扩大

使用该模型,要获取某个类别的所有文档,您需要以下内容:

select * from documents where categoryids like '%|' + @targetCategoryId + '|%'
我的解决方案是创建一个关联表,如下所示:

Document_Category
-------------------------------
DocumentID (PK)
CategoryID (PK)
这让开发人员感到困惑。有没有我遗漏的优雅的替代方案

我假设文档中将有数千行。类别可能有40行左右。主要关注点是查询性能。我是不是设计过度了

是否存在这样的情况,即最好将ID列表存储在数据库列中,而不是将数据推送到关联表中

还要考虑我们可能需要在文档之间创建多对多关系。这将建议使用关联表文档。这是首选设计还是将相关文档ID存储在一列中更好

谢谢

这让开发人员感到困惑


找到更好的开发人员。这是正确的方法。

使用逗号分隔的ID几乎总是一个大错误。

RDBMS是为存储关系而设计的。

您正在进行的多对多映射是很好的,并且是规范化的。如果需要,它还允许以后添加其他数据。例如,假设您想添加一个将类别添加到文档的时间

我建议在document_category表上也有一个代理主键。和一个唯一的(documentid,categoryid)约束,如果这样做有意义的话

为什么开发人员感到困惑

我的解决方案是创建一个 关联表如下:这是 让开发者感到困惑

真的吗?这是数据库101,如果这让他们感到困惑,那么他们可能需要远离向导生成的代码,学习一些基本的数据库规范化


你的建议是正确的解决方案

设计中的文档类别表无疑是解决问题的正确方法。如果可能的话,我建议您对开发人员进行教育,而不是提出一个次优的解决方案(并且受到性能影响,没有引用完整性)


其他选项可能取决于您使用的数据库。例如,在SQL Server中,可以有一个XML列,允许您将数组存储在预定义的模式中,然后根据该字段的内容进行连接。其他数据库系统可能也有类似的功能。

您的建议是优雅、强大、最佳实践的解决方案

因为我不认为其他的答案足够有力地表达了以下观点,所以我打算这么做

如果您的开发人员1)无法理解如何在关系数据库中建模多对多关系,2)强烈坚持将类别ID存储为分隔字符数据

然后他们应该立即失去所有数据库设计特权。至少,他们需要一位真正有经验的专业人士加入他们的团队,他们有权阻止他们做这种不明智的事情,并可以为他们提供他们完全缺乏的数据库设计培训

最后,在他们适当地掌握了最新的开发速度之前,您不应该再次将他们称为“数据库开发人员”,因为这对我们这些真正称职的开发人员和设计人员来说是一种轻视

我希望这个答案对你很有帮助

更新

我的问题的重点不是开发人员的困惑以及如何应对

关键是要理解分隔值何时是正确的解决方案

除极少数情况外,分隔值是错误的解决方案。当单个值被查询/插入/删除/更新时,这证明了这是一个错误的决定,因为您必须解析并触摸所有其他值才能使用所需的值。通过这样做,你首先违反了(!!!)正常形式(这句话听起来应该像一个令人难以置信的卑鄙咒骂)。使用XML做同样的事情也是错误的。如果将分隔值或多值XML作为不可分割且不透明的“属性包”处理,则在列中存储分隔值或多值XML是有意义的,数据库不会对其进行查询,但始终将其整体发送给另一个消费者(可能是web服务器或EDI收件人)

这让我回到我最初的评论。在我的书中,认为违反第一范式是个好主意的开发人员是非常缺乏经验的开发人员


我承认,现在有一些非常复杂的非关系数据存储实现,使用文本属性包(比如Facebook(?)和其他运行在数千台服务器上的数百万用户站点)。好吧,当你的数据库、用户群和每秒事务数足够大,需要这些数据时,你就有足够的钱来开发它了。同时,坚持最佳实践。

这让开发人员感到困惑