微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

不久之前,我一直在阅读 SQL and Relational Theory by C. J. Date一书.作者因批评sql的三值逻辑(3VL)而闻名.1)

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

1)日期对sql 3VL的批评反过来也受到批评:见this paper by Claude Rubinson(包括C. J. Date的原始批评).

示例表:

作为示例,请使用下表,其中我们有一个可为空的列(DateOfBirth):

#  +-------------------------------------------+
#  |                   People                  |
#  +------------+--------------+---------------+
#  |  PersonID  |  Name        |  DateOfBirth  |
#  +============+--------------+---------------+
#  |  1         |  Banana Man  |  NULL         |
#  +------------+--------------+---------------+

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

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

#  +------------------------------------------------------------------+
#  |                              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(因为它们会在结果集中引入NULL),所以可能不再像以前那样只使用一个查询获取所有必需的数据.

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

解决方法

我看到Date的同事Hugh Darwen在一个很好的演示文稿“如何处理不使用NULL的信息丢失”中讨论了这个问题,该文件the Third Manifesto website年发布.

他的解决方案是您第二种方法的变体.它是第六种常规形式,其中包含用于保存出生日期和未知标识符的表格:

#  +-----------------------------+ 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          |
#                                            +------------+

从People中选择然后需要加入所有三个表,包括样板,以指示未知的出生日期.

当然,这在某种程度上是理论上的.这些天的sql状态仍然不够先进,无法处理所有这些.休的介绍涵盖了这些缺点.他提到的一件事并不完全正确:sql的某些版本确实支持多个赋值 – 例如Oracle’s INSERT ALL syntax.

原文地址:https://www.jb51.cc/mssql/76754.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐