从DB模型中消除NULLable列的选项(为了避免SQL的三值逻辑)?

sta*_*ica 8 sql null relational-database three-valued-logic

不久前,我一直在阅读CJ Date的SQL和关系理论一书.作者因批评SQL的三值逻辑(3VL)而闻名.1)

作者强调了为什么在SQL中应该避免使用3VL,但是他没有概述如果不允许使用可空列的数据库模型的样子.我已经考虑了一点,并提出了以下解决方案.如果我错过了其他设计选项,我想听听他们的意见!

1)日期对SQL 3VL的批评反过来也受到了批评:请参阅 Claude Rubinson撰写的这篇论文(包括CJ Date的原始批评).


示例表:

举个例子,请看下面的表,我们有一个可以为空的列(DateOfBirth):

#  +-------------------------------------------+
#  |                   People                  |
#  +------------+--------------+---------------+
#  |  PersonID  |  Name        |  DateOfBirth  |
#  +============+--------------+---------------+
#  |  1         |  Banana Man  |  NULL         |
#  +------------+--------------+---------------+
Run Code Online (Sandbox Code Playgroud)

选项1:NULL通过标志和默认值进行模拟:

不是使列可为空,而是指定任何默认值(例如1900-01-01).另一BOOLEAN列将指定是否DateOfBirth应该忽略值in 或者它是否实际包含数据.

#  +------------------------------------------------------------------+
#  |                              People'                             |
#  +------------+--------------+----------------------+---------------+
#  |  PersonID  |  Name        |  IsDateOfBirthKnown  |  DateOfBirth  |
#  +============+--------------+----------------------+---------------+
#  |  1         |  Banana Man  |  FALSE               |  1900-01-01   |
#  +------------+--------------+----------------------+---------------+
Run Code Online (Sandbox Code Playgroud)

选项2:将可为空的列转换为单独的表:

可空列由新表(DatesOfBirth)替换.如果记录没有该列的数据,则新表中不会有记录:

#  +---------------------------+ 1    0..1 +----------------------------+
#  |         People'           | <-------> |         DatesOfBirth       |
#  +------------+--------------+           +------------+---------------+
#  |  PersonID  |  Name        |           |  PersonID  |  DateOfBirth  |
#  +============+--------------+           +============+---------------+
#  |  1         |  Banana Man  |
#  +------------+--------------+
Run Code Online (Sandbox Code Playgroud)

虽然这似乎是更好的解决方案,但这可能会导致需要为单个查询加入许多表.由于OUTER JOIN不允许使用s(因为它们会引入NULL结果集),因此可能不再像以前那样使用单个查询来获取所有必需的数据.


问题: 是否有其他消除选择NULL(如果是,它们是什么)?

APC*_*APC 5

我看到 Date 的同事 Hugh Darwen 在一篇精彩的演讲“如何在不使用 NULL 的情况下处理缺失信息”中讨论了这个问题,该演讲可以在第三宣言网站上找到。

他的解决方案是第二种方法的变体。它是第六范式,其中的表保存出生日期和未知的标识符:

#  +-----------------------------+ 1    0..1 +----------------------------+
#  |         People'             | <-------> |         DatesOfBirth       |
#  +------------+----------------+           +------------+---------------+
#  |  PersonID  |  Name          |           |  PersonID  |  DateOfBirth  |
#  +============+----------------+           +============+---------------+
#  |  1         |  Banana Man    |           ! 2          | 20-MAY-1991   |
#  |  2         |  Satsuma Girl  |           +------------+---------------+
#  +------------+----------------+
#                                  1    0..1 +------------+
#                                  <-------> | DobUnknown |
#                                            +------------+
#                                            |  PersonID  |
#                                            +============+
#                                            | 1          |
#                                            +------------+
Run Code Online (Sandbox Code Playgroud)

然后,从“人员”中进行选择需要连接所有三个表,包括指示未知出生日期的样板。

当然,这有些理论性。目前 SQL 的状态仍然不够先进,无法处理所有这些问题。休的演讲涵盖了这些缺点。他提到的一件事并不完全正确:某些 SQL 风格确实支持多重赋值 - 例如Oracle 的 INSERT ALL 语法