SQL:使用NULL值与默认值

时间:2010-01-22 10:56:57

标签: sql database ms-access database-design

在SQL中使用 NULL值 优点缺点是什么,而不是 < em>默认值

PS。这里已经提出了许多类似的问题,但没有人回答我的问题。

13 个答案:

答案 0 :(得分:38)

  

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

     

<强>赞成

     

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

     

NULL通常用于模式中   值是可选的。这很方便   省略数据录入的方法   不必要的未知领域   实施其他规则,比如   将负值存储在整数中   字段表示省略的数据。

     

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

     

虽然您的系统要求可能会   随时间变化和默认值   使用它们的类型,NULL值始终是   NULL所以不需要更新   数据类型。

     

为表模式分配非空   也可以帮助进行表格验证,   从某种意义上说,列没有   空标准需要值   插入。默认值不是   有这些能力。

     

<强>缺点

     

很容易将NULL值与之混淆   空字符串,返回   当用户的空白值   选择。从这个意义上讲,默认   价值观不那么混乱,而且是   更安全的选项,除非默认值   设置为空字符串。

     

如果允许NULL值   数据库,他们可能会导致设计师   一些额外的时间和工作尽可能   使数据库逻辑更多   复杂,特别是当有   很多与null值的比较   的地方。

来源:Pro and cons

答案 1 :(得分:17)

我不知道为什么你甚至试图将这些与案例进行比较。 null表示某些列为空/没有值,而当我们不在查询中直接设置时,默认值会为列提供一些值。

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

答案 2 :(得分:10)

空值不是......值!

Null表示'没有价值'...在数据库方面旁边,非值变量或字段的一个重要维度是不能使用'='(或'&gt;','&lt;') ,比较变量时。

写像(VB):

if myFirstValue = mySecondValue
如果一个或两个变量都是非值,

将不返回True或False。您将不得不使用“周转”,例如:

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

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

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

不严格正确,因为非值变量将被视为与'defaultValue'值(通常是零长度字符串)'相等'。

尽管有这种不愉快的行为,绝不会永远将默认值设置为零长度字符串(或'0')而没有宝贵的理由,并且在代码中缓和值的比较并不值得原因。

答案 3 :(得分:5)

NULL值表示该属性不适用或未知。有宗教战争争论他们是好事还是坏事,但我属于“好事”阵营。

在许多情况下,通常需要将已知值与未知值区分开来,并且对于那些没有合适默认值的属性,它们不需要哨兵值。

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

如果没有明确指定,默认值就是DBMS将放在列中的内容。

答案 4 :(得分:4)

对我来说,他们有点正交。

默认值允许您优雅地发展数据库模式(想想添加列),而无需修改客户端代码。另外,他们节省了一些打字,但依赖于默认值是IMO不好。

Null就是这样:null s。在处理Three-Valued Logic时缺少价值和巨大的PITA。

答案 5 :(得分:4)

与许多事情一样,每个事物都有好处和坏处。

关于默认值的优点:如果没有给出其他值,它们使您能够将列设置为已知值。例如,在创建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。这可能导致细微的错误,很难弄明白。

分享并享受。

答案 6 :(得分:4)

这取决于具体情况,但实际上最终很简单。哪一个更接近真相?

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

当您可以假设用户(或其他数据源)提供了值时,默认值很有用,该值将是默认值。如果这个推定确实会带来更大的危害,那么NULL就更好了,即使在SQL中处理NULL也很痛苦。

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

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

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

在理想的世界中,数据永远不会丢失。如果您正在为现实世界开发,最终将丢失所需的数据。您的应用程序可以执行某些有意义的操作,也可以执行在发生这种情况时无意义的操作。

答案 7 :(得分:3)

Null s和默认值是用于不同目的的不同内容。如果你试图通过给所有东西一个默认值来避免使用null,那么我将解释这是一个糟糕的做法。

Null表示我们不知道该值是什么或将是什么。例如,假设您有一个enddate字段。您不知道记录的进程何时结束,因此null是唯一合适的值;使用某个假日期的默认值将来会导致编程处理null的麻烦,并且更有可能在我的经验中创建返回错误结果的问题。

现在有时我们可能知道插入记录的人不应该是什么值。例如,如果您有一个date inserted字段,那么拥有当前日期的默认值并且不希望用户填写此字段是合适的。您可能实际上有更好的信息用于此字段。

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

所以我认为最好的规则是将值保留为null,如果您在输入数据时真正无法知道该字段的值应该是什么。使用默认值只有它具有该特定情况的所有时间,并使用其他技术填写值,如果它在不同情况下可能不同。

答案 8 :(得分:3)

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

相反,你会有“未知”,“未准备好”,“缺失”这样的价值

这样就可以在Fact and Dimension表上有效地执行INNER JOIN,因为“一切都有值”

答案 9 :(得分:1)

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

对任何说“空值”的人所宣称的任何东西都非常有用,就好像它是一个值。

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

这种看似非常简单的差异几乎无穷无尽。而这些后果中的大多数都是诱人的陷阱,让你感到非常糟糕。

答案 10 :(得分:0)

Allen Browne关于Nulls的两篇非常好的面向Access的文章:

在VBA代码中使用Nulls的方面:

这些文章是面向访问的,但对于那些使用任何数据库的人来说都很有价值,特别是相对新手因为写作的会话风格。

答案 11 :(得分:0)

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

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

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

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

答案 12 :(得分:0)

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