当前位置:  开发笔记 > 数据库 > 正文

关系数据库中的空值是否正常?

如何解决《关系数据库中的空值是否正常?》经验,为你挑选了13个好方法。

有一种观点认为在关系数据库中不应该允许空值.也就是说,表的属性(列)不应该允许空值.来自软件开发背景,我真的不明白这一点.似乎如果null在属性的上下文中有效,那么应该允许它.这在Java中非常常见,其中对象引用通常为null.没有广泛的数据库经验,我想知道我是否在这里遗漏了一些东西.



1> Adam Davis..:

从数据库规范化的角度来看,负面观点是否定的.这个想法是,如果一个值可以是空的,那么你真的应该把它拆分成另一个稀疏表,这样你就不需要没有值的项的行.

这是确保所有数据有效和有价值的努力.

在某些情况下,有一个空字段是有用的,特别是当你想出于性能原因而想要避免另一个连接时(尽管如果数据库引擎设置正确,这应该不是问题,除非在特殊的高性能方案中.)

-亚当


因此,如果您有一个非强制性的用户表和生日列,而所有其他列都是,那么您是否创建了一个生日表?听起来真的很傻.= |
我真的很好奇,什么时候数据库超标准化了?关系设计不能包含空值,如果稀疏表模式消除了null并且使数据库保持纯粹的关系,那么问题是什么?人们提到了连接,但我挑战了这个概念,因为与两个元组的关系几乎没有任何东西可以连接到基表,即使在极高的负载下也是如此.当然,影响只取决于设计生产力?人们没有规范化数据库,因为在某些时候,设计和查询变得更加困难.虽然努力应该改善这一点,而不是打破关系原则.
参考文献:CJ Date在关系数据库中非常有名.他是"被认为有害的无效"的主要支持者,例如见http://www.dcs.warwick.ac.uk/~hugh/TTM/Missing-info-without-nulls.pdf
@sr pt - 是的,这很傻.在遵循良好的规范化实践和数据库设计的理智之间存在平衡.两端都存在极端情况 - 数据库可能过于规范化.

2> Kristopher J..:

反对null的一个论点是它们没有明确定义的解释.如果字段为null,则可以将其解释为以下任何一种:

值为"Nothing"或"Empty set"

对于该领域没有任何价值.

价值未知.

该值尚未输入.

该值为空字符串(对于不区分空值和空字符串的数据库).

一些特定于应用程序的含义(例如,"如果值为null,则使用默认值.")

发生错误,导致该字段具有空值,而实际上不应该.

一些模式设计者要求所有值和数据类型都应具有明确定义的解释,因此空值很差.


整数也没有明确定义的含义.但没有什么可以阻止你通过文档添加一个.

3> Ken Wootton..:

空标记很好.真的,他们是.


如果没有解释,如果其他人发表了相反的意见,这个答案可能会变得毫无用处.例如,如果有人发布了像_这样的声明,那么"空标记就不行了.真的,它们不是."_,这个答案将如何帮助读者挑选出两种相反的观点?考虑[编辑]它,以更好地适应[答案]指南

4> Cade Roux..:

这取决于.

只要你理解为什么你NULL在数据库中允许s(需要按列进行选择)以及你将如何解释,忽略或以其他方式处理它们,它们就没问题了.

例如,一个专栏NUM_CHILDREN- 如果你不知道答案你会怎么做 - 它应该是NULL.在我看来,这个列的设计没有其他最佳选择(即使你有一个标志来确定NUM_CHILDREN列是否有效,你仍然必须在这一列中有一个值).

另一方面,如果你不允许NULLs并且对某些情况(而不是标志)有特殊的保留值,比如-1对于真正未知的子节点数,你必须以类似的方式解决这些问题,公约条款,文件等

因此,最终必须通过约定,文档和一致性来解决这些问题.

另一方面,正如Adam Davis在上述答案中明显支持的那样,将列规范化为稀疏(或者不是如此稀疏,在NUM_CHILDREN大多数数据具有已知值的示例或任何示例的情况下)表,同时能够消除所有NULL,在一般实践中是不可行的.

在许多属性未知的情况下,为每个列连接到另一个表是没有意义的,这可能允许NULL更简单的设计.连接的开销,主键的空间要求在现实世界中没有多大意义.

这让人想起通过添加基数列可以消除重复行的方式,同时它理论上解决了没有唯一键的问题,实际上有时是不可能的 - 例如,在大规模数据中.然后,纯粹主义者迅速建议替代PK,但是从关系理论的角度来看,无意义的代理可以构成关系(表格)中元组(行)的一部分的想法是可笑的.



5> Walter Mitty..:

使用NULL有几种不同的异议.一些反对意见是基于数据库理论.从理论上讲,理论与实践之间没有区别.在实践中,有.

确实,完全规范化的数据库可以在没有NULLS的情况下相处.任何必须省略数据值的地方都是可以省去整行但不丢失信息的地方.

实际上,将表分解到这个程度并没有什么用处,并且对数据库执行简单CRUD操作所需的编程变得更加繁琐且容易出错,而不是更少.

有些地方使用NULLS会导致问题:基本上这些问题围绕着以下问题:缺失数据究竟意味着什么?真正传达的所有NULL都是在给定字段中没有存储的值.但推理应用程序员从缺失的数据中抽取有时是不正确的,这会导致很多问题.

由于各种原因,某个位置可能会丢失数据.以下是一些:

    在此上下文中,数据不适用.例如,配偶一个人的名字.

    数据输入表单的用户将字段留空,并且应用程序不需要字段中的条目.

    数据从其他一些数据库或文件复制到数据库,并且源中缺少数据.

    在外键中编码可选关系.

    空字符串存储在Oracle数据库中.

以下是关于何时避免使用NULLS的一些指导原则:

如果在正常预期编程过程中,查询编写者必须编写大量ISNULL,NV,COALESCE或类似代码,以便将有效值替换为NULL.有时候,如果存储的是"现实",最好在商店时间进行替换.

如果计数可能会被关闭,因为计算了包含NULL的行.通常,只需选择count(MyField)而不是count(*)就可以避免这种情况.

这里有一个地方,你可以更好地习惯NULLS,并相应地编程:每当你开始使用外连接时,如LEFT JOIN和RIGHT JOIN.外连接背后的整点与内连接不同,是在缺少某些匹配数据时获取行.缺失的数据将作为NULLS提供.

我的底线:不理解它就不要理论.但要学会何时偏离理论以及如何遵循理论.



6> Ken..:

将NULL用于数据字段没有任何问题.将键设置为null时必须小心.主键永远不应为NULL.外键可以为null,但您必须小心不要创建孤立记录.

如果某些内容"不存在",那么您应该使用NULL而不是空字符串或其他类型的标志.


如果缺少某些内容,某些表中应该缺少一行."NULL"不是"缺失","NULL"是"任何东西".这需要重复.
"如果某些内容"不存在",那么你应该使用NULL而不是空字符串或其他类型的标志." 这需要重复
"将密钥设置为null时必须小心...."主键列*永远不能为*.作为主键一部分的任何列都不能为NULL.
如果缺少某些内容,某些表中应该缺少一行."NULL"不是"缺失","NULL"是"任何东西".这需要重复.(重复)

7> Mark Bracket..:

而不是写出NULL的所有问题,以及三态与布尔逻辑等等 - 我将提供这个精辟的建议:

    不要在列中允许NULL,直到您发现自己添加魔术值来表示丢失或不完整的数据.

    既然你问这个问题,你应该非常小心你如何处理NULL.它有很多非常明显的缺陷.如有疑问,请勿使用NULL.



8> finnw..:

还有另一种选择,使用"N/A"或"N/K"或空字符串 - 一个单独的表.

例如,如果我们可能知道或不知道客户的电话号码:

CREATE TABLE Customer (ID int PRIMARY KEY, Name varchar(100) NOT NULL, Address varchar(200) NOT NULL);
CREATE TABLE CustomerPhone (ID int PRIMARY KEY, Phone varchar(20) NOT NULL, CONSTRAINT FK_CustomerPhone_Customer FOREIGN KEY (ID) REFERENCES Customer (ID));

如果我们不知道电话号码,我们就不会在第二个表格中添加一行.



9> Vaibhav..:

我会说绝对应该使用Nulls.没有其他正确的方法来表示缺乏数据.例如,使用空字符串表示缺少的地址行是错误的,或者使用0表示缺少的年龄数据项是错误的.因为空字符串和0都是数据.Null是表示这种情况的最佳方式.


如果我们不知道是因为我们没有问过,或者他们拒绝透露它.如果是后者,是因为羞耻还是恶意?我们不能说.如果您的应用知道差异很重要,那么您可以将原因存储在其他地方.如果它不是重要的,谁在乎呢?
在Oracle中,一个空字符串,实际上是NULL :)

10> Andomar..:

不要通过使字段为NULL来低估您创建的复杂性.例如,以下where子句看起来会匹配所有行(位只能是1或0,对吧?)

where bitfield in (1,0)

但是如果位域是NULLable,它将会遗漏一些.或者采取以下查询:

select * from mytable
where id not in (select id from excludetable)

现在,如果excludetable包含null和1,则转换为:

select * from mytable
where id <> NULL and id <> 1

但是对于任何id值,"id <> NULL"都为false,因此这将永远不会返回任何行.这甚至可以吸引经验丰富的数据库开发人员.

鉴于大多数人都可以被NULL逮捕,我尽量避免使用它.



11> David Aldrid..:

这是一个巨大的蠕虫,因为NULL可能意味着很多东西:

没有死亡日期,因为这个人还活着.

没有手机号码,因为我们不知道它是什么,甚至它是否存在.

没有社会安全号码,因为该人知道没有社会安全号码.

其中一些可以通过规范化来避免,其中一些可以通过该列中存在的值("N/A")来避免,其中一些可以通过使用单独的列来解释NULL的存在来缓解("N/K","N/A"等).

它也是一种蠕虫,因为找到它们所需的SQL语法与非空值的SQL语法不同,很难加入它们,并且它们通常不包含在索引条目中.

由于前一个原因,您将找到无法避免null的情况.

由于后一种原因,您仍应尽力减少它们的数量.

无论如何,始终使用NOT NULL约束来防止需要值的空值.



12> ConcernedOfT..:

nulls的主要问题是它们具有特殊的语义,可以通过比较,聚合和连接产生意外的结果.

没有任何东西等于null,并且任何东西都不等于,大于或小于null,因此如果要进行任何批量比较,则必须将空值设置为占位符值.

这也是可能在连接中使用的复合键的问题.如果自然键包含可空列,您可能需要考虑使用合成键.

空值可以不计数,这可能不是你想要的语义.

您可以加入的列中的空值将消除内部联接中的行.一般来说,这可能是期望的行为,但它可以为进行报告的人打下大象陷阱.

null还有其他一些细微之处.Joe Celko的SQL for Smarties有一整章关于这个主题,是一本好书,无论如何都值得一读.空值是一个很好的解决方案的地方的一些例子是:

连接实体可能存在或不存在的可选关系.Null是表示外键列上的可选关系的唯一方法.

您可能希望使用null以退出计数的列.

可能存在或不存在的可选数字(例如货币)值.在数字系统中没有"未记录"的有效占位符值(特别是在零是合法值的情况下),因此null实际上是唯一的好方法.

您可能希望避免使用空值的地方的一些示例,因为它们可能会导致细微的错误.

代码字段上的"Not Recorded"值,对参考表使用FK.使用占位符值,因此在对数据库执行查询时,您(或某些随机业务分析师在轨道上)不会无意中从结果集中删除行.

没有输入任何内容的描述字段 - null string('')适用于此.这节省了必须将空值视为特殊情况.

报告或数据仓库系统上的可选列.对于这种情况,在维度中为"未记录"创建一个占位符行,并加入该行.这简化了查询,并与ad-hoc报告工具很好地配合使用.

同样,Celko的书是对这个主题的一个很好的对待.



13> ScottCher..:

关于普通形式的最好的事情是它们是指南和指南不应该被坚持遵守.当学术界与现实世界发生冲突时,你很少找到许多幸存的乙炔战士.

这个问题的答案是可以使用空值.只是评估您的情况并决定是否希望它们显示在表格中,或者如果您觉得空值与实际值的比率太高,则将数据折叠到另一个相关表格中.

正如朋友喜欢说的那样,"不要让完美成为善的敌人".想想伏尔泰也说过.8)

推荐阅读
135369一生真爱_890
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有