将数据库信息存储为数组

时间:2012-08-06 18:01:53

标签: php mysql arrays database

哪种做法很好?要将数据存储为数据库中的逗号分隔列表还是有多行?

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

4 个答案:

答案 0 :(得分:3)

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

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

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

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

  • Referential integrity(使用InnoDB)
    • 用关系描述的一致模型
    • 类型强制执行(不能有"foo,,"
  • 在没有需要自定义代码的情况下加入并查询
    • “A班学生的名字是什么?”
    • “谁参加了多个班级?”
    • 列可以是有用的索引(查询性能)
    • 通常比代码中的本地处理更快
  • 更灵活,更一致
    • 可以将属性附加到状态
    • 等注册
    • 无需使用代码来处理访问站点的序列化
    • 更多容纳占位符和ORM

答案 1 :(得分: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级课程的学生的名单。使用Plan 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恰好是列表中的第一个或最后一个,我们也找不到它,因为那时双方都没有逗号。

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

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

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

答案 2 :(得分:2)

我已经完成了两项工作,但是我没有以逗号分隔的方式将信息存储在数据库中,而是使用了另一个分隔符,例如|(这样我就不用担心插入到db中的格式化了)。它更多地是关于您查询数据的频率

答案 3 :(得分:1)

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