Database design 数据库设计:在数据库中保留分隔字符串是否不好

Database design 数据库设计:在数据库中保留分隔字符串是否不好,database-design,Database Design,我以前做过这样的项目:将字段存储在逗号分隔或管道分隔的字符串中作为字段,这可能表示选项或类似的内容。我想知道这样做是否被认为是糟糕的数据库设计,应该始终使用关系表,或者有时以这种方式存储数据是可以接受的?通常,这是一个坏主意 但是,规范化和性能之间有一个平衡 如果列表未被解析且只是按原样显示,则最好存储逗号分隔的列表,但如果列表是针对单个元素进行解析的,您应该坚持使用。这取决于-如果数据库不需要对分隔字符串中的数据进行任何类型的筛选或排序,并且数据最初是以分隔格式发送到数据库的,为什么不这样做?

我以前做过这样的项目:将字段存储在逗号分隔或管道分隔的字符串中作为字段,这可能表示选项或类似的内容。我想知道这样做是否被认为是糟糕的数据库设计,应该始终使用关系表,或者有时以这种方式存储数据是可以接受的?

通常,这是一个坏主意

但是,规范化和性能之间有一个平衡


如果列表未被解析且只是按原样显示,则最好存储逗号分隔的列表,但如果列表是针对单个元素进行解析的,您应该坚持使用。

这取决于-如果数据库不需要对分隔字符串中的数据进行任何类型的筛选或排序,并且数据最初是以分隔格式发送到数据库的,为什么不这样做?如果数据库永远不会使用它,为什么还要麻烦地解析它并将其拆分为单独的字段呢?

通常认为它不好,因为它违背了拥有数据库的目的(及其索引和搜索数据的强大方法)。然而,它可以根据具体情况加以证明。如果已经对分隔字符串进行了处理,并且除了检索它之外,您永远不想对该结构执行任何操作。。。谁来阻止你?

我会避免在数据库字段中放入带分隔符的字符串。字段应始终只包含一个值。这允许更大的灵活性,并允许您将数据库的内置功能用于大量聚合和其他功能:

例如,假设您有一个图书和作者数据库(常用于数据库图书)

  • 获得每个作者的书籍数量
  • 从作者处添加或删除一本书
  • 获取所有作者的图书总数

  • 可能性(几乎)是无穷的。但是,如果一个字段通过使用分隔符保存了多个值,那么每次需要这些基本函数的答案时,都需要对该字段进行解析。

    就我个人而言,我将通过两种方式来实现这一点:

    • 如果可行,我只需将逗号/管道分隔的列表转换为外键实现,并将该数据存储在另一个表中。如果您正在处理大量数据,这可能会有缺点,但在大多数情况下,这是可行的,并且如果您计划按这些字段进行查询,则通常希望采用这种方法

    • 另一种方法是简单地将数据存储为数据库中的序列化对象,而不是分隔列表。例如,在Python中,您可以使用
      pickle
      模块序列化标准对象,然后将其存储在数据库中,而不必担心代码执行和其他可能发生的恶意攻击

    这不是关系

    例如,如果您有:

    abc | 123,456,789
    def | 123
    ghi | 123
    
    将其标准化为如下内容:

    1 | abc | 123
    2 | abc | 456
    3 | def | 123
    4 | ghi | 123
    5 | abc | 789
    

    <>如果你发现越来越多的你需要使用存储在字符串中的值来搜索其他表,那么你应该考虑按照其他人的建议来规范数据库。Drupal、Wordpress等以字符串形式存储基本信息,并且在一定程度上运行良好。

    与所有优秀的设计问题一样,答案应该是“视情况而定”。关系数据库中的列旨在提供一个离散的逻辑信息单元,用于描述数据。我想说的是,如果没有任何理由通过列的内容来描述两个不同的数据段-也就是说,您永远不会希望找到一些数据,但不希望找到基于列内容的其他数据-这没关系


    例如,如果您将文件权限数据存储在列中,并且只保留数据以存储文件的权限,以便以后可以读取,那么就可以了。如果您想查询那些具有u+x权限的文件,而u+x权限是该列中数据的一个组成部分,则应将数据分隔为不同的列。

    这可能是一件好事。我曾经使用过几个使用数据库表记录SOAP请求和响应的系统。试图将所有这些数据标准化将是一个极其丑陋的过程。逗号分隔列表可能也有类似情况。

    这取决于您。数据库字段应该包含原子数据,也就是说,整个值有意义,但部分值没有意义。例如,我可能决定将一个人的名字存储在名为fullname的字段中,因此值为John Smith和Mary Jane等

    这是正确的,如果我将永远把这些值视为一个整体,永远不需要只选择名字或姓氏,或按姓氏排序等

    如果姓氏或名字对我有意义,也许我必须在查询中按姓氏排序,然后我将创建两个字段firstname和lastName


    在您的例子中,如果分隔项在数据库级别不感兴趣,那么可以将它们保留在单个字段中。但是,如果需要按分隔项进行查询,请将它们拆分为各自的字段。

    重要的是要记住,数据库是为了满足应用程序的需要而存在的,而不是反过来。如果你的应用程序需要存储管道分隔数据列表,那就这样吧

    这方面的一个很好的例子是我构建的一个管理工具。我需要大量关系数据的版本控制功能。我已经有了将上述数据序列化到JSON和从JSON序列化的例程,因此我创建了一个新的“版本”表,其中包含每个版本的一些标题信息和一个存储JSON版本的文本字段。编辑器还包括一个“激活”按钮,用于反序列化和规范化数据,并将其放在单独的表中,以便主应用程序可以访问其核心内容。请注意,primar从不修改此数据