1

哪个是好习惯?将数据作为逗号分隔的列表存储在数据库中还是有多行?

我有一个用于帐户、课程和注册的表格。如果注册表有 3 个字段:ID、AccountID 和 ClassID,ClassID 最好是一个包含逗号分隔列表的 varchar,例如:“24,21,182,12”,或者它只是一个 int 并且有一个每次注册?

4

4 回答 4

3

tldr:不要这样做。也就是说,不要在这里使用“打包数组”

使用具有“多行”的正确规范化设计。这可能是多对多关系的良好候选者。考虑这个结构:

Classes 1:M Enrollments(Class,Student) M:1 Students

遵循适当的标准化设计将减轻疼痛。此外,还有其他一些优点:

  • 参照完整性(使用 InnoDB)
    • 用关系描述的一致模型
    • 类型强制(不能有"foo,,"
  • 无需自定义代码 即可加入和查询
    • “A班的学生叫什么名字?”
    • “谁上了一门以上的课?”
    • 列可用于索引(查询性能)
    • 通常比在代码中本地处理更快
  • 更加灵活和一致
    • 可以将属性附加到注册,例如状态
    • 无需代码来处理访问站点的序列化
    • 更适应占位符和 ORM
于 2012-08-06T18:08:25.843 回答
3

永远不要通过将多个值与某种分隔符(如逗号或固定长度的子字符串)组合来将多个值填充到单个数据库字段中。在极少数情况下,这显然会在存储要求或性能方面带来好处……请参阅规则 #1:永远不会。曾经。

当您将多个值填充到单个字段中时,您会破坏数据库引擎中内置的所有巧妙功能,以帮助您检索和操作值。

就像假设你有这个——我猜它是某种学生数据库。

Plan A

student (student_id, account_id, class_id_mash)

Plan B

student (student_id, account_id)
student_class (student_id, class_id)

好的,假设您想要一个所有参加第 27 课的学生的列表。使用 B 计划,您可以编写

select student_id
from student join student_class on student.student_id=student_class.student_id
where class_id=27

简单的。

您将如何使用 A 计划?你可能认为

select student_id
from student
where class_id_mash like '%27%'

但这不仅会找到 27 班的所有学生,还会找到 127 或 272 班的所有学生。

好的,怎么样:

select student_id
from student
where class_id_mash like '%,27,%'

在那里,现在我们找不到 127 或 272!但是,哎呀,如果 27 恰好是列表中的第一个或最后一个,我们也不会找到它,因为两边都没有逗号。

好吧,也许我们可以通过更多关于分隔符的规则或更复杂的匹配表达式来解决这个问题。但这将是不必要的复杂和痛苦。

即使我们这样做了,每次对类 id 的搜索都必须是完全填充的顺序搜索。对于每个字段一个值和多个记录,您可以在 class_id 字段上创建一个索引,以便快速、高效地检索。(一些数据库引擎有办法索引到文本字段的中间,但是,当有一个简单的解决方案时,为什么还要进入复杂的解决方案呢?)

我们如何验证 class_id 的?使用单独的字段,我们可以说“class_id 引用类”,数据库引擎将确保我们不会输入非法值。有了 mash,没有这样的免费验证。

于 2012-08-06T18:16:03.640 回答
2

我两者都做了,但是我没有将数据库中的信息以逗号分隔,而是使用另一个分隔符,例如|(这样我就不用担心插入数据库时​​的格式)。它更多地是关于你多久查询一次数据

于 2012-08-06T18:05:13.270 回答
1

如果您只需要完整列表,则可以将其存储为逗号分隔值。但是如果你需要查询列表,它们应该分开存储。

于 2012-08-06T18:04:39.467 回答