Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database 在数据库列中存储分隔列表真的那么糟糕吗?_Database_Database Design_Database Normalization - Fatal编程技术网

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

Database 在数据库列中存储分隔列表真的那么糟糕吗?,database,database-design,database-normalization,Database,Database Design,Database Normalization,假设一个web表单有一组复选框(可以选择其中的任何一个或所有复选框)。我选择将它们保存在以逗号分隔的值列表中,这些值存储在数据库表的一列中 现在,我知道正确的解决方案是创建第二个表并正确地规范化数据库。实现easy解决方案的速度更快,我希望能够快速地证明该应用程序的概念,而不必花费太多时间 我认为在我的情况下,节省的时间和更简单的代码是值得的,这是一个合理的设计选择,还是我应该从一开始就规范化它 更详细地说,这是一个小型的内部应用程序,基本上可以替换存储在共享文件夹中的Excel文件。我这样问也

假设一个web表单有一组复选框(可以选择其中的任何一个或所有复选框)。我选择将它们保存在以逗号分隔的值列表中,这些值存储在数据库表的一列中

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

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


更详细地说,这是一个小型的内部应用程序,基本上可以替换存储在共享文件夹中的Excel文件。我这样问也是因为我正在考虑清理程序,使其更易于维护。有一些事情我并不完全满意,其中之一就是这个问题的主题。

是的,我想说它真的很糟糕。这是一个合理的选择,但这并不意味着它是正确的或好的

它打破了第一范式

第二个批评是,将原始输入结果直接放入数据库,而不进行任何验证或绑定,会使您容易受到SQL注入攻击

你称之为懒惰和缺乏SQL知识的东西是由新手组成的。我建议花点时间把它做好,并把它看作是一个学习的机会


或者让它保持原样,从SQL注入攻击中吸取惨痛的教训。

好吧,我在SQL Server中的一个NTEXT列中使用了一个键/值对选项卡分隔列表已经有4年多了,现在它可以工作了。您确实失去了进行查询的灵活性,但另一方面,如果您有一个库可以持久化/删除键值对,那么这不是一个坏主意。

有很多问题要问:

  • 如何从逗号分隔列表中获取特定值的计数
  • 如何从逗号分隔的列表中获取仅具有相同2/3/etc特定值的记录
逗号分隔列表的另一个问题是确保值的一致性-存储文本意味着可能出现打字错误


这些都是非规范化数据的症状,并强调了为什么您应该始终为规范化数据建模。反规范化可以是一种查询优化,在实际需要时应用

我可能会采取中间立场:将CSV中的每个字段都放在数据库中的一个单独的列中,但不必太担心规范化(至少目前如此)。在某种程度上,规范化可能会变得有趣,但由于所有数据都被推到一列中,使用数据库几乎没有任何好处。在对数据进行有意义的操作之前,您需要将数据划分为逻辑字段/列/您想调用的任何内容。

一般来说,任何符合项目要求的内容都是可以防御的。这并不意味着人们会同意或想要捍卫你的决定

通常,以这种方式存储数据是次优的(例如,更难进行有效的查询),如果修改表单中的项,可能会导致维护问题。也许你可以找到一个折衷方案,用一个整数来表示一组位标志?

“一个原因是懒惰”

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

话虽如此:如果您选择以这种方式存储的数据是您永远不需要查询的数据,那么可能需要以您选择的方式存储它

(一些用户可能会对我上一段中的说法提出质疑,称“你永远不知道将来会添加什么要求”。这些用户要么被误导,要么陈述了宗教信仰。有时候,按照你面前的要求工作是有利的。)

除了由于存储在单个列中的重复值组而导致冲突外,逗号分隔列表还有许多其他更实际的问题:

  • 无法确保每个值都是正确的数据类型:无法阻止1、2、3、5
  • 不能使用外键约束将值链接到查找表;无法强制引用完整性
  • 无法强制唯一性:无法阻止1,2,3,3,5
  • 如果不获取整个列表,则无法从列表中删除值
  • 存储的列表长度不能超过字符串列中的长度
  • 难以搜索列表中具有给定值的所有实体;您必须使用低效的表扫描。可能必须使用正则表达式,例如在MySQL中:
    idlist REGEXP'[[::]]'
    或在MySQL 8.0中:
    idlist REGEXP'\\b2\\b'
  • 很难计算列表中的元素,或执行其他聚合查询
  • 很难将值连接到它们引用的查找表
  • 很难按排序顺序获取列表
  • 很难选择保证不会出现在值中的分隔符
为了解决这些问题,您必须编写大量的应用程序代码,重新设计RDBMS已经提供的功能,使之更加高效

逗号分隔的列表是错误的,所以我在书的第一章中提到了这一点:

有时您需要采用非规范化,但作为例外情况。任何非关系性的“优化”都会使一种查询受益,而牺牲数据的其他用途,因此请确保您知道哪些查询需要特别处理,以便进行非规范化处理。

是的,这很糟糕。我的看法是