前段时间,我一直在阅读CJ Date的《 SQL 和关系理论》一书。作者以批评 SQL 的三值逻辑(3VL)而闻名。1)
作者对为什么在 SQL 中应避免使用 3VL 提出了一些要点,但他没有概述如果不允许可空列,数据库模型会是什么样子。我对此进行了一番思考,并提出了以下解决方案。如果我错过了其他设计选项,我想听听它们!
1) Date 对 SQL 3VL 的批评反过来也受到了批评:请参阅Claude Rubinson 的这篇论文(包括 CJ Date 的原始批评)。
示例表:
例如,以下表为例,我们有一个可为空的列 ( DateOfBirth
):
# +-------------------------------------------+
# | People |
# +------------+--------------+---------------+
# | PersonID | Name | DateOfBirth |
# +============+--------------+---------------+
# | 1 | Banana Man | NULL |
# +------------+--------------+---------------+
NULL
选项 1:通过标志和默认值进行模拟:
不是使列可以为空,而是指定任何默认值(例如1900-01-01
)。附加BOOLEAN
列将指定是否DateOfBirth
应该简单地忽略 in 的值,或者它是否实际包含数据。
# +------------------------------------------------------------------+
# | People' |
# +------------+--------------+----------------------+---------------+
# | PersonID | Name | IsDateOfBirthKnown | DateOfBirth |
# +============+--------------+----------------------+---------------+
# | 1 | Banana Man | FALSE | 1900-01-01 |
# +------------+--------------+----------------------+---------------+
选项 2:将可为空的列转换为单独的表:
可空列被新表 ( DatesOfBirth
) 替换。如果一条记录没有该列的数据,则新表中不会有记录:
# +---------------------------+ 1 0..1 +----------------------------+
# | People' | <-------> | DatesOfBirth |
# +------------+--------------+ +------------+---------------+
# | PersonID | Name | | PersonID | DateOfBirth |
# +============+--------------+ +============+---------------+
# | 1 | Banana Man |
# +------------+--------------+
虽然这似乎是更好的解决方案,但这可能会导致需要为单个查询连接许多表。由于OUTER JOIN
不允许 s (因为它们会引入NULL
结果集中),所有必要的数据可能不再像以前那样仅通过单个查询来获取。
问题:
是否还有其他消除方法NULL
(如果有,它们是什么)?