想象一个带有一组复选框的 Web 表单(可以选择其中任何一个或全部)。我选择将它们保存在存储在数据库表的一列中的逗号分隔值列表中。
现在,我知道正确的解决方案是创建第二个表并正确规范化数据库。实现简单的解决方案速度更快,我希望快速获得该应用程序的概念验证,而不必花费太多时间。
我认为在我的情况下节省的时间和更简单的代码是值得的,这是一个合理的设计选择,还是我应该从一开始就将其标准化?
更多上下文,这是一个小型内部应用程序,本质上替换了存储在共享文件夹中的 Excel 文件。我问这个问题也是因为我正在考虑清理该程序并使其更易于维护。其中有些事情我不太满意,其中之一就是这个问题的主题。
除了违反第一范式 http://en.wikipedia.org/wiki/1NF由于重复的值组存储在单个列中,因此逗号分隔的列表还有许多其他更实际的问题:
- 无法确保每个值都是正确的数据类型:无法阻止1,2,3,香蕉,5
- 不能使用外键约束将值链接到查找表;无法强制执行引用完整性。
- 无法强制执行唯一性:无法阻止1,2,3,3,3,5
- 在不获取整个列表的情况下无法从列表中删除值。
- 存储的列表长度不能超过字符串列的长度。
- 很难搜索列表中具有给定值的所有实体;你必须使用低效的表扫描。可能不得不求助于正则表达式,例如在 MySQL 中:
idlist REGEXP '[[:<:]]2[[:>:]]'
或者在 MySQL 8.0 中:idlist REGEXP '\\b2\\b'
- 很难对列表中的元素进行计数,或者进行其他聚合查询。
- 很难将值连接到它们引用的查找表。
- 很难按排序顺序获取列表。
- 很难选择保证不会出现在值中的分隔符
为了解决这些问题,您必须编写大量应用程序代码,重新发明 RDBMS 的功能已经提供了更有效的.
用逗号分隔的列表是错误的,我把它作为我书中的第一章:SQL 反模式,第 1 卷:避免数据库编程的陷阱 https://pragprog.com/titles/bksap1/.
有时您需要采用非规范化,但作为@OMG 小马提到 https://stackoverflow.com/a/3653507/578288,这些都是例外情况。任何非关系“优化”都会使一种类型的查询受益,但会牺牲数据的其他用途,因此请确保您知道哪些查询需要特别处理,以便它们值得非规范化。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)