在关系型数据库中,元组某个属性的值可能是一个未知值。在存储该元组时,对于这一无值的属性就需要先存储一个NULL占位符,等待该属性的值确定后再更新。
NULL占位符通常称为NULL值,也许这会给人造成误解,因为NULL并不是一个值,NULL只是意味着这个地方缺乏正常值。在数据库理论与实践中,NULL被看做是一个特殊的值:他可以作为任何属性域的一员,但又不同于任何域中的其它值。NULL也不等于它自己。
空值在查询中经常产生一些令人头疼的问题。EG:条件p_customer.cstname=’远方’中,如果属性cstname上有空值的元组,那么该条件的真值是什么呢?
因为有这类数据的存在,所以SQL中使用了所谓的三值逻辑,包括:true,false,unknown.当val1和val2中至少有一个是NULL时,val1 op val2( op 可以是>,<,<>,=等)就被认为是unknown.
空值不仅影响到where之句和check之句中的比较,还影响到算术表达式和聚合函数。
当算术表达式遇到NULL时,它自身就被定值为NULL. Count(*)把NULL当做正常值,在count某一具体列时会将空值归为一类来处理,所有其它的聚合则把空值丢掉,然而还是要注意,如果将这样的聚合函数应用到只有NULL的列上,那么结果还是空值。
当where子句或者check子句形如cond1 AND cond2,cond1 OR cond2 或 NOT cond,并且子条件之一因为有NULL隐藏在其中而计算得到unknown时。依赖于子条件的布尔函数的真值表如下:
COND1 |
COND2 |
COND1 and COND2 |
COND1 or COND2 |
TRUE |
TRUE |
TRUE |
TRUE |
TRUE |
FALSE |
FALSE |
TRUE |
TRUE |
UNKNOWN |
UNKNOWN |
TRUE |
FALSE |
TRUE |
FALSE |
TURE |
FALSE |
FALSE |
FALSE |
FALSE |
FALSE |
UNKNOWN |
FALSE |
UNKNOWN |
UNKNOWN |
TRUE |
UNKNOWN |
TURE |
UNKNOWN |
FALSE |
FALSE |
UNKNOWN |
UNKNOWN |
UNKNOWN |
UNKNOWN |
UNKNOWN |
COND |
NOT COND |
TRUE |
FALSE |
FALSE |
TRUE |
UNKNOWN |
UNKNOWN |
上述表比较清晰的介绍了子条件的布尔值对照关系,其基本思想也比较简单,假设我们需要介绍true and unknown 的值。因为unknown可能是true 或者是false ,所以整个表达式的值就可能是true或者是false (也就是unknown).其它布尔值情况也可以做类似解释。
SQL 中引入了另一个谓词 IS NULL,它用来测试某个值是否为NULL.EG:当赋予p_customer某一元组在cstname属性上有空值的时候,cstname is null 为真,否则为假。有趣的是这是SQL中唯一真正的二值谓词。
当整个子句计算得到UNKNOWN时,将会怎么样呢?答案要取决于这是一个WHERE子句还是一个CHECK子句。如果WHERE子句计算得到UNKNOWN,就被视为FALSE,相应的元组也不能加入查询结果。如果CHECK子句计算得到UNKNOWN,就要考虑遵守完整性约束了(也就是结果被视为TRUE).
空值对于LIKE条件,IN条件,集合比较(EG: > ALL ),EXISTS特性,消除重复(如用到DISTINCT的查询)等等都会产生影响,在实际应用中应多注意。