在数据库列中存储分隔列表真的很糟糕吗?

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

现在,我知道正确的解决方案是创建第二个表并正确地规范数据库。 实施简单解决方案的速度更快,我希望能够快速获得该应用程序的概念验证,而不必花费太多时间。

我认为节省的时间和简单的代码在我的情况下是值得的,这是一个可靠的设计选择,还是应该从一开始就将其规范化?

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


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

  • 不能确保每个值是正确的数据类型:没有办法防止1,2,3,香蕉,5
  • 无法使用外键约束将值链接到查找表; 没有办法强制参照完整性。
  • 无法强制执行唯一性:没有办法阻止1,2,3,3,3,5
  • 无法从列表中删除值而不提取整个列表。
  • 无法存储比列中字符串长的列表。
  • 很难搜索列表中给定值的所有实体; 您必须使用低效的表扫描。 可能不得不求助于正则表达式,例如在MySQL中:
    idlist REGEXP '[[:<:]]2[[:>:]]'
  • 很难对列表中的元素进行计数,或执行其他聚合查询。
  • 很难将这些值加入到他们引用的查找表中。
  • 很难按排序顺序获取列表。
  • 将整数存储为字符串需要的空间大约是存储二进制整数的两倍。 更不用说逗号字符所占用的空间了。
  • 为了解决这些问题,您必须编写大量的应用程序代码,重新创建RDBMS已经提供的功能,从而提高效率。

    逗号分隔的列表是错误的,我在本书的第一章做了这个:SQL反模式:避免数据库编程的陷阱。

    有时候你需要使用非规范化,但正如@OMG Ponies所说,这些都是例外情况。 任何非关系型的“优化”都会以牺牲数据的其他用途为代价使一种查询受益,因此请确保您知道哪些查询需要特别处理,以至于他们应该得到非规范化。


    †MySQL 8.0不再支持这种边界表达式语法。


    SO提出了许多问题:

  • 如何从逗号分隔列表中获得特定值的计数
  • 如何从该逗号分隔列表中获得只具有相同2/3 /等特定值的记录
  • 逗号分隔列表的另一个问题是确保值一致 - 存储文本意味着错别字的可能性...

    这些都是非规格化数据的所有症状,并强调为什么您应该始终为归一化数据建模。 非规范化可以是查询优化, 在需求实际出现时应用


    “其中一个原因是懒惰”。

    这响起警钟。 你应该这样做的唯一原因是你知道如何做到“正确的方式”,但你得出的结论是有一个切实的理由不这样做。

    说了这么一句话:如果您选择以这种方式存储的数据是您永远不需要查询的数据,那么可能存在以您选择的方式存储它的情况。

    (有些用户会对我上一段的陈述提出异议,说“你永远不知道将来会增加什么要求”,这些用户要么被误导了,要么表达宗教信仰,有时候根据你的要求工作是有好处的。在你面前。)

    链接地址: http://www.djcxy.com/p/41307.html

    上一篇: Is storing a delimited list in a database column really that bad?

    下一篇: Enum Naming Convention