【问题标题】:Is better use an empty value as a '' or as NULL?使用空值作为 '' 还是 NULL 更好?
【发布时间】:2012-11-12 14:02:19
【问题描述】:

数据库架构

我有这个字段:

  • 标题(字符串)
  • 字幕
  • 描述(字符串)

最好将默认值设置为空字符串''还是NULL

为了更好的读/写和大小存储性能

【问题讨论】:

  • 我认为取决于您的客户端代码的预期?
  • 没关系。我将根据此调整客户端代码
  • 我认为您应该问问自己数据库中的有效日期是什么,以及您希望如何查询它。例如,如果描述一个空的描述是有效的,我会使用一个空字符串。一般来说,如前所述,NULL 用于指示未知数据,但如果空字符串是有效的已知数据,则应使用空字符串。我只在必要时才使用 NULL。

标签: mysql ruby-on-rails database postgresql database-design


【解决方案1】:

通常的合同是:

  • NULL 表示“无可用信息”。
  • '' 的意思是“有可用的信息。它只是空的。”

NULL 在任何语言中的发明以来,还有很多哲学讨论,而不仅仅是 SQL。

这里唯一的技术点是:在 PostgreSQL 中,NULL 可以比长度为零的字符串更有效地存储。如果这对你来说真的很重要......我们不知道。

【讨论】:

  • 我可以阅读更多信息,为什么 PostgreSQL 更有效地存储 Null 值?
  • @user1028100 是的,搜索“postgresql null bitmap”或阅读手册中的存储结构文档。
【解决方案2】:

您应该始终使用 NULL 来表示该列没有值,因为即使是空字符串也是一个值。

【讨论】:

  • 对此有广泛的争论。有相当大的学校认为数据库中的 NULL 表明数据库设计不佳。我自己尽量避免使用 NULL,尽管我并不热衷于它
  • @SebastianCabot:NULL 怎么可能表明设计不好?存在数据完全未知的有效情况,在这种情况下,唯一有效的选择是存储NULL
  • @a_horse_with_no_name 正如我所说,对此存在争议。我推荐阅读 C.J Date 的“SQL 和关系理论”。简而言之。使用 NULL 表示没有数据意味着您设计的数据库不能包含任何数据。从关系理论的角度来看,每个可能的值都将使用外键连接到行——这样你就没有真正的表,而是属于一个实体的值。该行将使用连接查询构造,因此如果没有数据,则不会将值存储在数据库中。 NULL 的存在是因为很难有效地实现这个方案。
  • @mu,Codd 对关系数据库系统的规则之一是应该有“缺失值的系统处理”。我和你在一起。 “系统处理”并不意味着不惜一切代价避免丢失数据。现实世界有时会很不方便。但我承认,SQL 布尔值 UNKNOWN 有时会让我感到困惑,因为我是在两个有价值的逻辑中长大的。并且 NULL=NULL 会产生 UNKNOWN。
  • @SebastianCabot “使用 NULL 表示没有数据意味着您设计的数据库不能包含任何数据。”是荒谬的归约。创建一个不允许空值且不包含数据的数据库很容易。任何做过数据清理练习的人都会熟悉包含' ''.' 的列:用户对该字段没有任何价值,但应用程序坚持要输入something。坦率地说,我宁愿处理一个 NULL 而不是一个神奇的 vlue 或垃圾。
【解决方案3】:

您需要确定“null”和空字符串的值在您的应用程序中是否意味着不同的含义,或者它们都只是意味着“无数据”。如果是后者,那么这通常只是一个偏好问题,但你必须随之而来 - 尽量不要在给定字段中混合“空”值和空值。

通常,'null' 提供了更好的“无数据”概念,但与空字符串相比,它在应用程序中使用起来有些麻烦。但是,使用空字符串代替空字符串可能会被视为过早的优化,并且在将来的某个时间将无法引入需要区分空字符串和空字符串的功能。

另一方面,有些 DBMS 不将空值存储在字符串列中,只存储空字符串。我会选择空值,但要使用完善且有据可查的合同(即“此字段从不包含空值,空标题意味着没有标题”,在列上强制执行 NOT NULL 约束),您可以采取任何您喜欢的方法。

如果您关心性能,则需要阅读您正在使用的 DBMS 的文档并自行进行一些测试。如果您希望空值非常频繁,您可以检查“稀疏列”是否有任何帮助 - 一些 DBMS 引入这些作为有效存储频繁出现的空值的手段,但它们通常有一些缺点,例如一般 (通常不会很大)检索非空值或类似的东西时性能损失。

当然,您还必须考虑客户的期望。但是,当您创建尚未被客户访问的数据库时,由您决定并适当地记录它。

【讨论】:

    【解决方案4】:

    仅当数据未知或不适用时才使用 Null 值。在所有其他情况下,使用 ""(空值),因为在编写涉及 NULL 值的数据的查询时需要特别注意,这通常很困难..

    【讨论】:

      【解决方案5】:

      这并不严格适用于您的情况,但为了完整起见,我会提到它:不强制使用 NULL 外键。

      如果您有一个字段 foreign_id 是引用其他表的外键,则仅当 foreign_id 包含非 NULL 值时才会强制执行。

      顺便说一句,甲骨文stores empty string as NULL。保证 VARCHAR2 继续以这种方式运行,而 VARCHAR 可能(有朝一日)被更改以符合 SQL 标准并区分空字符串和 NULL。其他 DBMS(据我所知)确实有这种区别。

      【讨论】:

      • 感谢您指出这一点。这意味着在 postgresql 上,您不能在外键中使用的列中使用空字符串 ('')。例如:create table tab2(col1 varchar(10));alter table tab2 add constraint tab2_pk primary key(col1);create table tab1(colA varchar(10), col1 varchar(10));alter table tab1 add constraint fk_tab1_tab2 foreign key (col1) references tab2(col1);insert into tab1 values ('A','');ERROR: insert or update on table "tab1" violates foreign key constraint "fk_tab1_tab2"insert into tab1 values ('A',null);INSERT 0 1 (OK)
      【解决方案6】:

      关于这一点已经说了很多,但我认为还有一件事要考虑如果你最终认为使用 NULL 或“”作为“无价值”之间是 50/50(简单地说) .

      在 MySQL 中,如果您对列有否定条件,则不会“捕获”NULL 值。例如。

      where column != 'text'
      

      只会返回 "column" 没有值 "text" 但不会找到 "column" 为 NULL 的行,如果您还想找到这些行,您必须使用:

      where column != 'text' OR column IS NULL
      

      我自己还是更喜欢在保存之前使用NULL并将空字符串更改为nil,我认为最好知道“空值”在数据库中始终为NULL。

      另一方面,在某些情况下,您可能希望使用“无值”(NULL)和“空值”(“”)之间的差异。但我在某些应用程序中从未遇到过这种情况。

      【讨论】:

        【解决方案7】:

        这取决于。你知道值是空的吗?示例:已知人没有中间名首字母。

        或者你只是不知道?示例:您收到了“中间名首字母”字段留空的表格。

        【讨论】:

          【解决方案8】:

          专家意见:避免空值

          Dr. Chris (C.J.) Date 与关系数据模型的创建者/发现者 (Dr. Codd) 合作,他明确表示:“不,你不应该使用 NULL。”。阅读他的书A Guide To The SQL Standard 进行更多讨论。

          他和其他专家认为,对于各种理论和实践问题,NULL 会带来太多的风险、混乱和问题,使它们变得有价值。

          解决方案:

          • NOT NULL 的每一列上添加一个约束。
          • 在有意义的地方,为每一列添加一个默认值DEFAULT。对于文本类型列,默认值可能是空字符串 ('')。或者,默认值可能是您任意选择和一致使用的某个措辞,例如“EMPTY”或“NOT-AVAILABLE”,具体取决于您的需要。在某些列上,您可能不需要默认值,这意味着如果用户/应用未提供值,您希望拒绝记录的插入或更新。

          规则的例外

          以上是一个很好的规则,我习惯性地遵循它。但是,每条规则都有例外。在极少数情况下,我允许 NULL 例外。

          示例例外:Postgres 中使用XML data type 在数百万行的表中。我需要反复搜索尚未记录值的行(缺失值)。我无法存储空字符串,因为 Postgres 强制执行仅存储有效 XML 的规则,而空字符串不是有效的 XML 文档。所以我允许在那个 XML 列中使用 NULL。

          您可能认为我可以存储一个不包含数据的最小 XML 文档。但我不知道如何有效地建立索引,以区分记录数据的行和没有记录数据的行。我可以在 NULL 上创建索引。

          【讨论】:

            猜你喜欢
            • 2011-05-21
            • 2018-08-23
            • 2021-03-21
            • 2018-01-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-24
            • 2016-04-03
            相关资源
            最近更新 更多