Warm tip: This article is reproduced from serverfault.com, please click

其他-在数据库列中存储定界列表真的那么糟糕吗?

(其他 - Is storing a delimited list in a database column really that bad?)

发布于 2010-09-06 18:11:25

想象一下带有一组复选框的Web表单(可以选择其中的任何一个或全部)。我选择将它们保存在以逗号分隔的值列表中,该值列表存储在数据库表的一列中。

现在,我知道正确的解决方案是创建第二个表并正确规范化数据库。实施简单的解决方案的速度更快,我想快速地对该应用程序进行概念验证,而不必花太多时间在它上面。

我认为节省时间和更简单的代码在我的情况下是值得的,这是一个合理的设计选择,还是我应该从一开始就对其进行标准化?

在更多情况下,这是一个小型内部应用程序,实际上替代了存储在共享文件夹中的Excel文件。我也在问,因为我正在考虑清理程序并使其更易于维护。我有些不满意,有些是这个问题的主题。

Questioner
Mad Scientist
Viewed
11
Bill Karwin 2021-02-10 14:01:20

除了由于存储在单个列中的值重复组而违反第一范式之外,逗号分隔的列表还有许多其他更实际的问题:

  • 无法确保每个值都是正确的数据类型:无法阻止1,2,3,banana,5
  • 不能使用外键约束将值链接到查找表;无法强制执行参照完整性。
  • 无法强制唯一性:无法阻止1,2,3,3,3,5
  • 在不获取整个列表的情况下无法从列表中删除值。
  • 列表的存储时间不能超过字符串列的容纳时间。
  • 很难在列表中搜索具有给定值的所有实体;你必须使用效率低下的表格扫描。可能不得不求助于正则表达式,例如在MySQL中
    idlist REGEXP '[[:<:]]2[[:>:]]'或在MySQL 8.0中:idlist REGEXP '\\b2\\b'
  • 难以计数列表中的元素,或执行其他汇总查询。
  • 很难将值连接到它们引用的查找表中。
  • 难以按排序顺序获取列表。
  • 很难选择一个保证不会出现在值中的分隔符

为了解决这些问题,你必须编写大量的应用程序代码,以重新创建RDBMS已经提供的功能,从而更加有效

逗号分隔的列表是非常错误的,以至于我将其作为本书的第一章:SQL反模式:避免数据库编程的陷阱

有时候你需要使用非规范化,但是正如@OMG Ponies所提到的,这是例外情况。任何非关系式“优化”都会以一种查询类型为代价,而以其他用途使用数据为代价,因此,请确保你知道哪些查询需要特别处理,以使它们值得进行非规范化处理。