Sql 如何避免数据库中出现空值,同时也表示丢失的数据?

Sql 如何避免数据库中出现空值,同时也表示丢失的数据?,sql,database,database-design,schema,data-modeling,Sql,Database,Database Design,Schema,Data Modeling,在(C.J.Date,2009)第4章中,我们主张避免重复行,并避免存储数据中的NULL属性。虽然我在避免重复行方面没有问题,但我正在努力了解如何在不使用NULL的情况下对数据建模。以下面的例子为例,这是工作中的一部分 我们有一个artist表,其中包括gender列。这是gender表的外键。然而,对于一些艺术家来说,我们不知道他们的性别——例如,我们收到了一份没有艺术家描述的新音乐列表。如果不使用NULL,如何表示此数据?我看到的唯一解决方案是在gender表中添加一个新的性别“unknow

在(C.J.Date,2009)第4章中,我们主张避免重复行,并避免存储数据中的
NULL
属性。虽然我在避免重复行方面没有问题,但我正在努力了解如何在不使用
NULL
的情况下对数据建模。以下面的例子为例,这是工作中的一部分

我们有一个
artist
表,其中包括
gender
列。这是
gender
表的外键。然而,对于一些艺术家来说,我们不知道他们的性别——例如,我们收到了一份没有艺术家描述的新音乐列表。如果不使用
NULL
,如何表示此数据?我看到的唯一解决方案是在
gender
表中添加一个新的性别“unknown”

虽然我非常喜欢这本书,但当这一章以以下内容结束时,我真的很失望:

当然,如果禁止空值,那么丢失的信息将不得不通过其他方式处理。不幸的是,这些其他方法过于复杂,无法在此详细讨论

这是一个真正的耻辱-因为这是我等待阅读的解决方案!有一个参考阅读附录,其中有很多出版物要读,但我希望在我开始阅读这些之前,能有一个更为实际的总结


有一些人评论说,他们不明白我为什么希望避免“NULL”,所以我将再次引用这本书。以下面的查询为例:

SELECT s.sno, p.pno
  FROM s, p
 WHERE s.city <> p.city
    OR p.city <> 'Paris'
选择s.sno,p.pno
来自s,p
s.city p.city在哪里
或p.城市“巴黎”
现在,以s.city是伦敦,p.city是巴黎为例。在这个例子中,伦敦是巴黎,所以这个疑问是正确的。现在假设p.city不是巴黎,实际上是xyz。在这种情况下,(伦敦xyz)或(巴黎xyz)也是正确的。因此,给定任何数据,这个查询都是正确的。但是,如果xyz为“NULL”,则场景会发生变化。在这种情况下,这两个表达式既不是真的也不是假的,它们实际上是未知的。在这种情况下,因为结果未知,所以不会返回任何行

从2值逻辑到3值逻辑的转变很容易引入这样的错误。事实上,我刚刚在工作中介绍了一个激发这篇文章的因素。我想要
类型!=0
然而,这实际上会导致匹配
类型==0或类型为空
——混淆行为


我将来是否使用
NULL
对数据建模尚不清楚,但我很好奇其他解决方案是什么。(我也一直认为,如果你不知道,你应该使用
NULL
)。

空值是必需的-没有必要替换它们

enitre对NULL的定义是它的未知性——简单地用任意类型替换它就是在做同样的事情,那么为什么呢

有关以下评论:

刚刚尝试过这个-两者都不是真的:

declare @x char
set @x = null

if @x = @x
begin
select 'true'
end

if @x <> @x
begin
select 'false'
end
declare@x char
设置@x=null
如果@x=@x
开始
选择“真”
结束
如果@x@x
开始
选择“false”
结束

我只能认为这意味着,因为null是未知的,所以不能说它等于或不等于-因此这两个陈述都是错误的

null
s是理论符合现实的结果,必须调整才能使用。在我看来,试图避免所有
null
值最终会导致比在适当的情况下使用
null
更难看、更不易维护的代码。

我不同意作者的观点,并声称null实际上是处理可选字段缺失数据的正确方法。事实上,这就是NULL存在的原因

关于你的性别问题:

  • 是否确实需要一个性别表,并为每个查询产生额外联接的成本?对于简单枚举类型,将字段设为int并定义1=male、2=male、NULL=unknown并非不合理

只需存储已知信息,即封闭世界假设。目标是至少达到Boyce Codd/Fifth Normal Form,这样你就不会犯太大的错误。

NULL
可以/应该使用,只要:

A你有商业理由。例如,在付款表中,
NULL
payment值表示从未付款。
0.00
付款值意味着我们故意不付款。对于医疗图表,血压读数的
NULL
值表示您没有测量血压,
0
值表示患者死亡。这是一个显著的区别,在某些应用中是必要的

B)您的查询说明了这一点。如果您了解
NULL
对中的
的影响,
存在
、不等式运算符(如您在OP中指定的)等,那么这不应该是一个问题。如果您的表中现在有
NULL
,并且不需要某些应用程序的值,您可以使用视图和
COALESCE
ISNULL
来填充不同的值(如果源表有
NULL

编辑:

为了解决OP关于使用
NULL
的“真实世界”不等式/等式的问题,这是我有时使用的一个很好的例子

你和另外三个人在一个聚会上。你知道一个人叫“约翰”,但不认识其他人

从逻辑上讲“有多少人被命名为乔”的答案是未知的或
NULL
。在SQL中,这类似于

从name='Joe'所在的party中选择name
您将不会得到任何行,因为您不知道它们的名称。他们可能是也可能不是乔

你的不平等将是:

从名为“Joe”的聚会中选择姓名
您将