【问题标题】:SQL: Using NULL values vs. default valuesSQL:使用 NULL 值与默认值
【发布时间】:2011-01-08 04:07:55
【问题描述】:

在 SQL 中使用 NULL 值默认值

PS。此处已提出许多类似问题,但没有人回答我的问题。

【问题讨论】:

  • 具有默认值使得 WHERE 语句可以跨数据库移植,有多种方法可以处理 NULL。如果您有一个默认值,您可以像使用 = 的任何其他值一样对其进行测试,而不必执行 IS/IS NOT。

标签: sql database ms-access database-design


【解决方案1】:

对我来说,它们有些正交。

默认值允许您优雅地发展您的数据库架构(考虑添加列),而无需修改客户端代码。另外,它们节省了一些输入,但依赖默认值是 IMO 不好的。

空值就是:nulls。与Three-Valued Logic 打交道时缺少价值和巨大的 PITA。

【讨论】:

  • 缺失值本身就是一个值......在很多用例中,“无值”具有特定含义,用“神奇值”(如 -99999)代替 null没有简化任何事情;消费代码必须检查“if X.HasValue()”或“if X == -99999”。
【解决方案2】:

数据库中的 NULL 值是一个系统 占用一个字节的值 存储并指示一个值是 与空间相反,不存在或 零或任何其他默认值。这 数据库中包含的字段 NULL值表示内容 这个细胞在当时是未知的 看着它。允许的列 NULL 值还允许行 插入时根本没有任何值 柱子。有几个优点和 相反使用 NULL 值的缺点 默认值:

优点

NULL 值没有数据 类型,因此可以插入到任何 数据结构和任何数据库 柱子。默认值,另一方面 手,需要有他们的数据类型 指定和一个默认值 列可能在另一个中看起来相同 列,但它可能是不同的 类型。

NULL 常用于 值是可选的。这是一个方便的 省略数据输入的方法 未知领域而不必 实施其他规则,例如 将负值存储在整数中 字段来表示省略的数据。

由于NULL值只占1 一点内存空间,它们可能是 在优化数据库时很有用。 使用这些值要多得多 比默认值有效,例如 字符的 8 位和整数的 16位。

虽然您的系统要求可能 随时间变化和默认值 类型与他们,NULL 值总是 NULL 所以不需要更新 数据类型。

将 Not Null 分配给表模式 还可以帮助进行表格验证, 从某种意义上说,带有 Not 的列 空标准将需要一个值 被插入。默认值不 拥有这些能力。

缺点

NULL 值很容易与 空字符串,返回 给用户一个空白值时 选择。从这个意义上说,默认 值不那么令人困惑,并且是 更安全的选项,除非默认值 设置为空字符串。

如果在 数据库,它们可能会导致设计者 一些额外的时间和工作,他们可以 让数据库逻辑更丰富 复杂的,尤其是当有 很多与空值的比较 地点。

来源:Pro and cons

【讨论】:

  • 此外,使用 NULLS 会产生三值逻辑。如果 X 为 3,则布尔值(例如 X=3)的值为 true。如果 X 的值不是 3 但不为 NULL,则其值为 false。如果 X 为 NULL,则布尔值的值为“未知”。未知是第三个逻辑值。对于习惯于两种有价值的逻辑的人来说,这可能会让他们感到困惑。
  • link 烂了
【解决方案3】:

我不知道您为什么要尝试将这些与案例进行比较。 null 表示某些列是空的/没有值,而默认值在我们不直接在查询中设置时给列一些值。

也许一些例子会更好的解释。假设我们有member 表。每个成员都有一个 ID 和用户名。可选的,他可能有一个电子邮件地址(但他不必)。此外,每个成员都有一个 postCount 列(每次用户写帖子时都会增加)。所以 e-mail 列可以有一个 null 值(因为 e-mail 是可选的),而 postCount 列是 NOT NULL 但有默认值 0 (因为当我们创建一个新成员时,他没有任何帖子)。

【讨论】:

  • 因为我对使用这两个的概念不太了解,谢谢。
【解决方案4】:

NULL 值表示该属性不适用或未知。宗教战争是好是坏,但我属于“好东西”阵营。

在许多情况下,它们通常是区分已知值和未知值所必需的,并且对于那些没有合适的默认值的属性,它们使标记值变得不必要。

例如,虽然银行余额的默认值可能为零,但手机号码的默认值是多少。您可能需要区分“客户没有手机”和“客户的手机号码(尚)未知”,在这种情况下,空白列不会起作用(并且有一个额外的列来决定该列是一列还是其他不是一个好主意)。

如果您没有明确指定默认值,DBMS 将在列中放入它。

【讨论】:

  • 000-000-0000 或 555-555-5555 或任何其他无效的电话号码是一个很好的默认电话号码,您可以测试的任何内容在理论上都与针对 NULL 进行测试一样好,但更容易在实践中。
  • 我不同意,模糊。您正在使用的是哨兵,一个虚假的真实值来指示有关该字段的元数据。在某些情况下,所有可能的值都是有效的,没有一个可以用作哨兵。此外,在查询中放入“is null”并不比“= '000-000-0000'”更难(而且通常更节省空间来存储 null)所以我不确定你有什么问题 NULL这让事情变得更难了。
【解决方案5】:

空值不是……值!

Null 表示“没有值”……除了数据库方面,无值变量或字段的一个重要维度是不能使用“=”(或“>”、“

编写类似 (VB) 的东西:

if myFirstValue = mySecondValue

如果一个或两个变量都没有值,则不会返回 True 或 False。您将不得不使用“周转”,例如:

if (isnull(myFirstValue) and isNull(mySecondValue)) or myFirstValue = mySecondValue

在这种情况下使用的“通常”代码是

if Nz(myFirstValue) = Nz(mySecondValue, defaultValue)

不完全正确,因为非值变量将被视为“等于”“默认值”值(通常是零长度字符串)。

尽管有这种令人不快的行为,never never never 没有任何有价值的理由将默认值设为零长度字符串(或“0”),并且在代码中轻松进行值比较并不有价值原因。

【讨论】:

    【解决方案6】:

    与许多事情一样,各有优劣。

    关于默认值的优点:如果没有给出其他值,它们使您能够将列设置为已知值。例如,在创建 BOOLEAN 列时,我通常给列一个默认值(TRUE 或 FALSE,任何合适的值)并使列 NOT NULL。通过这种方式,我可以确信该列将具有一个值,并且它会被适当地设置。

    关于默认值的缺点:并非所有事物都有默认值。

    关于 NULL 的好处:并非所有事物在任何时候都具有已知值。例如,在创建代表一个人的新行时,我可能没有所有列的值 - 假设我知道他们的名字但不知道他们的出生日期。为出生日期设置默认值是不合适的 - 如果他们的生日实际上是 7 月 22 日,人们不喜欢在 1 月 1 日(如果这是默认值)收到生日贺卡。

    NULL 的坏处:NULL 需要小心处理。在大多数建立在关系模型上的数据库中,通常实现的 NULL 是有毒的 - 计算中存在 NULL 会导致计算结果为 NULL。比较中使用的 NULL 也可能导致意外结果,因为任何与 NULL 的比较都会返回 UNKNOWN(既不是 TRUE 也不是 FALSE)。例如,考虑以下 PL/SQL 脚本:

    declare 
      nValue NUMBER;
    begin
      IF nValue > 0 THEN
        dbms_output.put_line('nValue > 0');
      ELSE
        dbms_output.put_line('nValue <= 0');
      END IF;
    
      IF nValue <= 0 THEN
        dbms_output.put_line('nValue <= 0');
      ELSE
        dbms_output.put_line('nValue > 0');
      END IF;
    end;
    

    上面的输出是:

    nValue <= 0
    nValue > 0
    

    这可能有点令人惊讶。至少根据此代码,您有一个 NUMBER (nValue) 既小于或等于零又大于零。发生这种情况的原因是 nValue 实际上是 NULL,并且所有与 NULL 的比较都会导致 UNKNOWN 而不是 TRUE 或 FALSE。这可能会导致难以发现的细微错误。

    分享和享受。

    【讨论】:

      【解决方案7】:

      这取决于具体情况,但归根结底其实很简单。哪一个更接近真相?

      很多人处理数据时就好像它只是数据一样,真相并不重要。但是,每当您与数据中的利益相关者交谈时,您会发现真相总是很重要。有时更多,有时更少,但这始终很重要。

      当您假设用户(或其他数据源)提供了一个值时,默认值很有用,该值将是默认值。如果这种假设弊大于利,那么 NULL 更好,尽管处理 NULL 在 SQL 中很痛苦。

      请注意,可以通过三种不同的方式实现默认值。首先,在应用程序中,在插入新数据之前。数据库永远不会看到用户提供的默认值与应用程序提供的默认值之间的区别!

      其次,通过为列声明一个默认值,并在插入中保留缺失的数据。

      第三,通过在检索时替换默认值,只要检测到 NULL。只有少数 DBMS 产品允许在数据库中声明第三种模式。

      在理想世界中,数据永远不会丢失。如果您正在为现实世界开发,最终会丢失所需的数据。当这种情况发生时,您的应用程序可以做一些有意义的事情,也可以做一些没有意义的事情。

      【讨论】:

        【解决方案8】:

        Nulls 和默认值是用于不同目的的不同事物。如果您试图通过为所有内容指定默认值来避免使用nulls,那么我将解释这是一种不好的做法。

        Null 表示我们不知道该值是什么或将是什么。例如,假设您有一个 enddate 字段。你不知道被记录的过程什么时候结束,所以null是唯一合适的值;将来使用某个假日期的默认值将导致编程的麻烦与处理nulls 一样多,并且根据我的经验,更有可能造成返回错误结果的问题。

        现在,如果插入记录的人不知道,有时我们可能会知道该值应该是什么。例如,如果您有一个date inserted 字段,则使用当前日期的默认值而不期望用户填写它是合适的。您实际上可能会以这种方式获得更好的信息。

        有时,这是一种判断,取决于您必须应用的业务规则。假设您有一个speaker honoraria 字段(这是演讲者将获得的报酬)。 0 的默认值可能很危险,因为这可能意味着演讲者已被雇用,而我们不打算向他们支付任何费用。也有可能偶尔会有演讲者为特定项目贡献时间(或者他们是公司的员工,因此没有支付额外费用),其中零是正确的值,所以你不能使用零作为确定您不知道该扬声器的报酬是多少的价值。在这种情况下,Null 是唯一合适的值,如果有人试图将发言人添加到会议中,代码应该会触发问题。在不同的情况下,您可能已经知道任何演讲者的最低报酬是 3000,并且只有协商不同费率的演讲者才会在honoraria 字段中输入数据。在这种情况下,输入默认值3000 是合适的。在另一种情况下,不同的客户端可能有不同的最小值,因此应该以不同的方式处理默认值(通常通过查找表自动填充数据输入表单上该客户端的最小 honoraria 值。

        所以我觉得最好的规则是将值保留为null,如果您在输入数据时确实不知道该字段的值应该是什么。仅使用默认值,它在特定情况下始终有意义,如果在不同情况下可能有所不同,请使用其他技术来填充该值。

        【讨论】:

          【解决方案9】:

          在数据仓库中,您总是希望使用默认值而不是 NULL。

          相反,您将获得诸如“未知”、“未准备好”、“缺失”之类的值

          这允许在 Fact 和 Dimension 表上高效地执行 INNER JOIN,因为“每件事都有一个值”

          【讨论】:

            【解决方案10】:

            正如一位响应者已经说过的,NULL 不是一个值。

            当任何人把“NULL 值”当成一个值说出来时,请务必小心。

            NULL 不等于自身。如果 x 和 y 都为 NULL,则 x=y 产生 false。如果 x 和 y 都是默认值,则 x=y 产生 true。

            这种看似非常简单的区别几乎会产生无穷无尽的后果。而这些后果中的大多数都是诱杀陷阱,对你造成严重伤害。

            【讨论】:

              【解决方案11】:

              Allen Browne 撰写的关于 Null 的两篇非常好的面向访问的文章:

              在 VBA 代码中使用 Null 的各个方面:

              这些文章是面向 Access 的,但对于那些使用任何数据库的人来说都是有价值的,尤其是相对的新手,因为它采用了对话式的写作风格。

              【讨论】:

                【解决方案12】:

                空值永远不会在 DB2 for OS/390 和 z/OS 中节省存储空间。每个可为空的列都需要一个额外的存储字节用于空指示符。因此,可为空的 CHAR(10) 列每行需要 11 个字节的存储空间——10 个用于数据,1 个用于空指示符。无论该列是否设置为空,都是这种情况。

                用于 Linux、Unix 和 Windows 的 DB2 有一个压缩选项,允许将列设置为 null 以节省空间。使用此选项会导致 DB2 从列设置为空的行中消除未使用的空间。但是,此选项在大型机上不可用。

                参考号:http://www.craigsmullins.com/bp7.htm

                因此,DB2 Z/OS 的最佳建模实践是使用“NOT NULL WITH DEFAULT”作为所有列的标准。在我认识的一些主要商店中也是如此。无需处理 Null 指示器,使程序员的生活更加轻松,并且通过消除为 NULL INDICATOR 使用额外字节的需要,实际上节省了存储空间。

                【讨论】:

                  【解决方案13】:

                  我非常感谢所有这些讨论。我正在构建一个数据仓库,并且相当严格地使用 Kimball 模型。然而,有一个非常直言不讳的用户,他讨厌代理键并希望到处都是 NULL。我告诉他可以为维度属性和计算中使用的任何日期或数字设置 NULLable 列,因为默认值意味着不正确的数据。我同意,在某些列中允许使用 NULL 是有好处的,但是如果一个维度的每个外键都有一个代理键,即使对于一个虚拟记录,该代理是 -1 或 0,它也会使立方体变得更好和更可靠. SQL 喜欢整数用于连接,如果缺少维度值并且提供了一个虚拟作为代理键,那么您将使用一个维度获得与在另一个维度上进行立方计算相同数量的记录。但是,必须正确完成计算,并且您必须在其中容纳 NULL 值。例如,生日应该为 NULL,以便不计算年龄。我相信良好的数据治理并与用户一起做出这些决定会迫使他们以比以往更多的方式思考他们的数据。

                  【讨论】:

                    猜你喜欢
                    • 2011-08-06
                    • 2012-12-15
                    • 2011-07-05
                    • 2010-10-03
                    • 2013-04-28
                    • 2019-08-17
                    • 1970-01-01
                    • 2012-01-18
                    • 2020-12-25
                    相关资源
                    最近更新 更多