代码之家  ›  专栏  ›  技术社区  ›  Jerod Venema

我应该在数据库模式中允许空值吗?

  •  27
  • Jerod Venema  · 技术社区  · 16 年前

    我知道在逻辑上,有些情况下,在数据库模式中,空值是有意义的,例如,如果没有指定普通值。这就是说,在代码中处理dbnull往往是一种极大的痛苦。例如,如果我正在呈现一个视图,并且我想要看到一个字符串,我希望没有值是空字符串,而不是“空”,我讨厌在这个场景中编写代码。

    此外,它使查询更加容易。诚然,您可以很容易地做到“foo不为空”,但对于初级SQL开发人员来说,不能够使用“foo”是违反直觉的!=null”(是的,我知道关闭ansi null s等选项,但这绝对不简单,我不喜欢脱离标准工作)。

    在数据库模式中拥有/允许空值有什么好的理由?

    15 回复  |  直到 12 年前
        1
  •  41
  •   Aaron Alton    16 年前

    允许空值的最重要原因是没有合理的选择。逻辑上,空值表示“未定义”。由于缺少空值,您最终将尝试在结果未定义的任何位置指定一个“假”值,然后您将不得不在所有应用程序逻辑中解释所说的“假”值。

    我写了一篇关于在数据库中包含空值的原因的博客文章。你可以找到它 here . 总之,我相信空值是数据库设计的一个组成部分,应该使用 在适当的情况下 .

        2
  •  11
  •   Mark Lutton    16 年前

    C.J.Date在他的书《SQL和关系理论》(2009:O'Reilly;ISBN 978-0-596-52306-0)中对空值采取了非常强烈的立场。他演示了在SQL中存在空值会对某些查询给出错误的答案。(参数不适用于关系模型本身,因为关系模型不允许空值。)

    我试着用文字来概括他的例子。他给出了一个表S,其中包含属性sno(供应商编号)和city(供应商所在城市)以及一行(s1,伦敦)。还有一个具有属性pno(零件号)和city(生产零件的城市)和一行(p1,空)的表P。现在他做了一个查询“get(sno,pno)pairs”,其中要么供应商和部分城市不同,要么部分城市不是巴黎(或者两者都不是)。

    在现实世界中,p1是在一个既不是巴黎也不是巴黎的城市中生成的,因此查询应该返回(s1,p1),因为部分城市要么是巴黎,要么不是巴黎。(表P中仅存在p1意味着零件有一个与其相关联的城市,即使未知。)如果是巴黎,那么供应商和零件城市是不同的。如果不是巴黎,那部分城市就不是巴黎。但是,根据三值逻辑的规则,(london)计算为unknown,(null<>'paris')计算为unknown,unknown或unknown减少为unknown,这不是真的(也不是假的),因此不会返回行。查询“select s.sno,p.pno from s,p其中s.city<>p.city或p.city<>'paris'为空表,这是错误的答案。

    我不是专家,目前还没有准备好在这里接受赞成或反对。我确实认为C.J.Date是关系理论最重要的权威之一。

    另外,您也可以将SQL用作关系数据库以外的其他数据库。它可以做很多事情。

        3
  •  6
  •   Quassnoi    16 年前

    在数据库模式中拥有/允许空值有什么好的理由?

    从理论的角度来看, NULL 表示没有为列定义值。

    在你想说的任何地方使用它” 我不知道/我不在乎 “回答问题” 这个列的值是多少?

    从性能的角度来看,以下是一些提示:

    • Oracle , 无效的 的没有索引。您可以使用 无效的 对于不需要索引的值。
    • 甲骨文公司 拖尾 无效的 不占空间。
    • 不像零点, 无效的 可以安全地除以。
    • 无效的 的确有贡献 COUNT(*) 但不要参与 COUNT(column)
        4
  •  4
  •   Mladen Prajdic    16 年前

    当您的列确实可以有一个没有默认值的未知值时,空值很好。 如果您的专栏适用于该规则,我们无法回答。

    例如,如果您有和结束日期,则可能会尝试将datetime.maxvalue作为默认isntead为空。这是完全有效的,但你必须考虑到报告正在做的这类事情。

        5
  •  3
  •   Walter Mitty    16 年前

    理论上,理论和实践没有区别。实际上是这样的。

    理论上,可以设计一个不需要空值的数据库,因为它是完全规范化的。每当一个值被省略时,包含它的整行都可以省略,因此不需要任何空值。

    然而,为了得到这个结果,你必须经历的表分解的程度,仅仅是不值得从理论美学的角度获得收益。通常最好让一些列包含空值。

    对于可以为空的列,很好的候选者是这样的:除了数据是可选的之外,在WHERE或HAVING子句的比较条件中永远不会使用该列。不管您信不信由您,外键通常可以在其中使用空值,以指示不存在的关系实例。内部联接将除去空值以及包含空值的行。

    当一个值经常在布尔条件下使用时,最好设计为不发生空值。否则,您可能会得到一个神秘的结果,在SQL中,“not unknown”的值是“unknown”。这给你之前的许多人造成了错误。

        6
  •  2
  •   Joel Coehoorn    16 年前

    通常,如果允许数据库中的列为空,则该空值有一些单独的 意思 关于数据库本身的结构。例如,在 StackOverflow database schema ,post表中parentID或tags列的空值表示post是问题还是答案。只要确保在每种情况下,含义都有良好的文档记录。

    现在,您的特别抱怨是在客户机代码中处理这些值。有两种缓解问题的方法:

    • 大多数具有上述含义的案例都不应首先回到客户那里。在查询中使用空来收集正确的结果,但不要返回空列本身。

    • 对于其余的情况,通常可以使用coalesce()或isnull()函数来返回一些更容易处理的函数。

        7
  •  1
  •   Guffa    16 年前

    每当需要指定根本没有值时,空值都很有用。

    您可以使用幻数,但处理空值比处理幻数更直观,而且更容易记住要处理的值。(Hm.)魔法值是-1、99999还是99999…?)

    另外,魔法值没有任何真正的魔法,任何情况下都不会有安全措施阻止你使用魔法值。计算机不知道你不能用-1乘42,因为在这种情况下-1恰好是一个不合理的值,但它知道你不能用零乘42。

    对于文本值,空字符串可以用作“无值”,但也存在一些缺点。例如,如果一个字段中有三个空格,则在视觉上不可能与空字符串区分开来,但它们是不同的值。

        8
  •  1
  •   HLGEM    16 年前

    输入原始数据时(例如,订单上的发货日期)信息可能不可用时,应使用或必须使用空值。

    当然,在某些情况下,空值可能表示需要重新设计(大多数字段中由空项组成的表可能没有正确规范化,可能不需要包含所有空值的文件)。

    不要使用空值,因为JR开发人员没有正确理解它们,这表明您的问题比空值大。任何不了解如何访问包含空值的数据的开发人员都需要接受SQL中的基本培训。这和不使用触发器来强制执行数据完整性规则一样愚蠢,因为当出现问题时,开发人员忘记查看它们,或者由于开发人员不理解它们而不使用联接,或者由于开发人员太懒,无法添加字段名,所以使用select*。

        9
  •  1
  •   JonBWalsh    16 年前

    除了其他答案中提到的重要原因之外,空值对于现有产品的新版本非常重要。

    向已经存在的表中添加新的可以为空的列的影响相对较小。由于数据迁移,添加一个新的不可为空的列是一个更加复杂的过程。如果您或您的客户拥有大量数据,迁移的时间和复杂性可能会成为一个重大问题。

        10
  •  0
  •   kemiller2002    16 年前

    具有空值的原因

    1. 这是一个公认的实践,每个做数据库工作的人都知道nulls是如何工作的。
    2. 它清楚地表明存在一个值的缺失。
        11
  •  0
  •   Bill Karwin    16 年前

    就其价值而言,SQL-99定义了一个谓词 IS [NOT] DISTINCT FROM 返回真或假,即使操作数为空。

    foo IS DISTINCT FROM 1234
    

    相当于:

    foo <> 1234 OR foo IS NULL
    

    PostgreSQL、IBM DB2和Firebird支持 IS DISTINCT FROM .

    Oracle和Microsoft SQL Server还没有。

    mysql有自己的操作符 <=> 工作原理是 IS NOT DISTINCT FROM .

        13
  •  0
  •   Erwin Smout    16 年前

    在逻辑上,从来没有空值有意义的情况。空不是关系模型的一部分,关系理论也没有空这样的概念。

    空值是“有用的”,从这个意义上说,蹩脚的DBMS让你别无选择,只能在物理层面上使用它,而那些同样蹩脚的DBMS本身严重地混淆了逻辑层面,或多或少地迫使他们的用户做同样的事情。

        14
  •  0
  •   Jody    16 年前

    我同意这里的大多数答案,但要用不同的方式来分阶段,“你不能有一个值,这意味着两件事”。只是有点困惑。0真的是0吗?还是说我们还不知道?等。

        15
  •  0
  •   Nadeera kodithuwakku    12 年前

    当有一个实体的属性没有值时,我们使用一个空值。空值不是0,但它不是值。一个例子是大多数韩国人的名字都没有中间名。如果有名字、中间名和姓氏的name属性,则应提供一个特殊值空值。