为什么要在SQL数据库中避免空值?

为什么要在SQL数据库中避免空值?,sql,database-design,Sql,Database Design,我今天从一家著名的SQL工具商业供应商那里读了一篇关于开发人员数据库性能提示的45提示文档,其中有一个提示让我感到困惑: 如果可能,请避免数据库中的空值。如果没有,请使用 适当的代码为空且不是空代码 我喜欢空值,因为对我来说,如果一个值从未设置过,或者它0或字符串为空,那么它就不同了。所以数据库里有这个 那么,这是一个无稽之谈,还是应该采取措施防止数据库表中出现空值呢?如果使用NULL值而不是填充的number或string值,会对性能产生很大影响吗?我认为在数据库中使用NULL值是可行的,直到

我今天从一家著名的SQL工具商业供应商那里读了一篇关于开发人员数据库性能提示的45提示文档,其中有一个提示让我感到困惑:

如果可能,请避免数据库中的空值。如果没有,请使用 适当的代码为空且不是空代码

我喜欢空值,因为对我来说,如果一个值从未设置过,或者它
0
字符串为空,那么它就不同了。所以数据库里有这个


那么,这是一个无稽之谈,还是应该采取措施防止数据库表中出现空值呢?如果使用
NULL
值而不是填充的
number
string
值,会对性能产生很大影响吗?

我认为在数据库中使用NULL值是可行的,直到您的应用程序有适当的逻辑来处理它,但根据本文,可能会出现一些此处讨论的问题

空值有许多缺点,这使得使用空值比实际值更困难。例如:

  • 在某些情况下,它们没有索引
  • 它们使得连接语法更加困难
  • 他们需要特殊的处理来进行比较
  • 对于字符串列,使用“N/A”或“N/K”作为特殊值可能比较合适,这有助于区分可能为空的不同类别,但对于数字或日期来说,这很难做到——特殊值通常很难使用,最好添加一个额外的列(例如,对于出生日期,您可能会有一个列指定“不出生日期的原因”,这可以帮助应用程序更加有用

    对于许多数据值确实未知或不相关的情况,它们当然是完全合适的——死亡日期或账户终止日期就是一个很好的例子


    有时,通过将事件标准化到不同的表中,甚至这些示例也可能变得无关紧要,因此您有一个“帐户日期”表,日期类型为“打开”、“关闭”,等等。

    空问题并不简单……每个专业人士都有自己的看法

    关系理论二值逻辑(2VL:TRUE和FALSE)拒绝NULL,Chris Date是NULL的最大敌人之一。但是Ted Codd也接受三值逻辑(TRUE、FALSE和UNKNOWN)

    对于Oracle,只需注意以下几点:

  • 单列B*树索引不包含空项。因此,如果您编码“WHERE XXX IS NULL”,优化器将无法使用索引

  • Oracle将NULL视为空字符串,因此:

    WHERE SOME_FIELD = NULL
    
    同:

    WHERE SOME_FIELD = ''
    
  • 此外,对于NULL,您必须在查询中注意,因为每次使用NULL进行比较都返回NULL。 有时,空值是阴险的。请考虑以下情况:

    WHERE SOME_FIELD NOT IN (SELECT C FROM SOME_TABLE)
    
    如果子查询返回一个或多个null,则得到空记录集


    这些是我想讨论的最初几个案例。但是我们可以在很多时候谈论空值…

    避免或尽量减少空值的使用通常是一种很好的做法。空值会导致一些查询返回“不正确”的结果(即,结果与数据库的预期含义不符)。不幸的是,SQL和SQL样式的数据库可能会使空值难以避免,尽管不一定是不可能的。这是一个非常现实的问题,甚至专家也常常难以发现由空值引起的查询逻辑中的缺陷

    因为在现实世界中没有比null更好的东西,所以使用它们意味着在数据库表示现实的方式上做出一些妥协。事实上,没有单一的一致的“意义”在实践中,null被用来表示各种不同的情况。如果你真的使用它们,最好准确地记录null对于任何给定属性的含义

    以下是Chris Date关于“零问题”的精彩演讲:


    除了其他答案中提到的原因之外,我们可以从不同的角度来看待空值

    关于重复行,Codd说

    如果某件事是真的,说两遍并不能使它变得更真实

    同样地,你可以说

    如果某件事不为人所知,说它不为人所知并不代表它为人所知。

    数据库用于记录事实。事实(真相)作为公理,我们可以从中推断其他事实。
    从这个角度来看,不应该记录未知的事情——它们不是有用的事实。
    不管怎么说,任何没有被记录的东西都是未知的。那为什么还要记录它们呢?

    更不用说它们的存在使推理复杂化了。< / P>在适当的时候使用NULL。永远不要考虑对空值的“替代”。我的2C。“将所有列标记为
    notnull
    ,除非您确实仔细考虑过,并且希望接受该列中的
    NULL
    s“这也说明了标准化。缺少值可能与缺少行直接相关。也许这应该与合并?Codd不接受3VL,正如批评者所说的那样。根据证据,(a)他接受可能必须记录未知值,以及(b)他给出了一种方法,它不是3VL,而是2VL。Codd的关系理论拒绝数据中的NULL,但NULL可以出现在结果集中,因此无法回避代码必须处理NULL这一事实,不管它是否在数据中。Codd当然提出了3VLs,具有未知。标准SQL允许某些未知和未知的用法我们将取而代之。