我主要对MySQL和PostgreSQL感兴趣,但是您通常可以回答以下问题:在逻辑上有一种区分空字符串和NULL有用的方案吗?

将空字符串存储为...的物理存储含义是什么?


NULL?
空字符串?
另一个字段?
还有其他方法吗?




#1 楼

假设记录来自表单以收集姓名和地址信息。如果用户不住在公寓里,那么地址的第2行通常为空白。在这种情况下,空字符串是完全有效的。我倾向于使用NULL来表示该值未知或未给出。

我不认为实际中的物理存储差异值得担心。作为数据库管理员,我们还有很多要炸的鱼!

评论


+1很少有dba需要担心是否使用NULL的速度/大小差异

–帕特里克(Patrick)
2011年1月4日,0:52

同意...我尝试为“未知”保留NULL ...空字符串为“我们知道它应该为空”。当您的数据来自多个来源时,此功能特别有用

–乔
2011年1月4日,下午1:27

杰出-未知NULL,指定了空字符串。

–ScottCher
2011年1月4日21:32

@Larry对性能有何影响?在多列表与多行表之间,性能如何变化?

– Shimmy Weitzhandler
15年3月13日在5:01

我同意,如果在数据集中没有给出值与空字符串之间存在区别,那么您应该适当地使用它们,但是就我个人而言,如果我的数据不需要这种区别,那么我总是使用空字符串,纯粹是因为我发现在命令行上来自MySQL客户端的查询结果可以更干净地查看空字符串而不是很多NULL

– RTF
18年11月22日在10:27

#2 楼

我不了解MySQL和PostgreSQL,但让我对此进行一般性的介绍。

有一个DBMS,即Oracle,不允许在NULL和''之间选择用户。
这清楚地表明,不必区分两者。
有一些烦人的后果:

将varchar2设置为一个空字符串,如下所示:

Update mytable set varchar_col = '';


以下结果相同。

Update mytable set varchar_col = NULL;


但是要选择值为空或NULL的列,则必须使用

select * from mytable where varchar_col is NULL;


从语法上来说,使用

select * from mytable where varchar_col = '';


是正确的,但是它从不返回任何行。

另一方面,在Oracle中连接字符串时。 NULL varchars被视为空字符串。

select NULL || 'abc' from DUAL;

产生abc。在这种情况下,其他DBMS将返回NULL。

要明确表示要分配值时,必须使用''。

担心是否修剪不为空会导致NULL

select case when ltrim(' ') is null then 'null' else 'not null' end from dual


会。

现在看一下DBMS,其中''与NULL不相同(例如SQL-Server)

使用”通常更容易,并且在大多数情况下,实际上没有必要区分两者。我知道的例外之一是,当您的列代表某种设置而您没有为它们设置默认值时。当您可以区分''和NULL时,可以表示您的设置为空,并避免使用默认设置。

评论


相关:stackoverflow.com/questions/203493/…

–乔
2011年1月4日在16:53

#3 楼

这取决于您正在处理的域。 NULL表示没有值(即没有值),而空字符串表示长度为零的字符串值。例如,假设您有一个表来存储一个人的数据,包含一个Gender列。您可以将值另存为“男性”或“女性”。如果用户能够选择不提供性别数据,则应将其另存为NULL(即用户未提供值)并且不为空字符串(因为不存在带有值''的性别)。

评论


如果用户选择不提供性别,则一定要存储“拒绝提供”。 NULL是模棱两可的;也可能表示“未询问客户”,“客户使用不在我们列表中的性别标识”等。

–万事通
2015年1月7日15:52

#4 楼

值得牢记的一件事是,当您有一个不需要的字段,但是存在的任何值必须唯一时,将需要您将空值存储为NULL。否则,您只能在该字段中具有一个带有空值的元组。

关系代数和NULL值也有一些区别:例如NULL!= NULL。

评论


实际上不是NULL!= NULL,因为那是NULL。 ;-)

– Peter Eisentraut
2011年1月4日,下午5:10

请注意,MS SQL不遵循此规则:多个NULL值将违反UNIQUE约束。幸运的是,从2008年开始,您可以使用过滤索引来获得正确的行为。

–万事通
15年1月7日在15:50

#5 楼

您可能还会考虑Date对NULL的评论以及SQL和关系理论中的3VL问题(以及Rubinson对Date的评论,空值,三值逻辑和SQL中的歧义的评论:对Date的评论)。

在相关的SO线程中都对这两种方法进行了详细的引用和讨论,这是从数据库模型中消除可空列的选项。

#6 楼

一个新的想法,对您选择NULL / NOT NULL的影响很大,如果您使用的是框架。我大量使用symfony,并使用允许NULL字段简化了处理数据时的某些代码和数据检查。

如果您不使用框架,或者使用简单的sql语句和处理,我会选择您认为更容易掌握的任何选择。我通常更喜欢使用NULL,这样在执行INSERT语句时就不会因为忘记将空字段设置为NULL而变得乏味。

评论


问题是关于NULL与空字符串(在可为空的列,IMO中),而不是NULL与NOT NULL,不是吗?

–甘
2011年1月4日,下午2:01

关于存储的问题部分使我认为他可能也在考虑Null / Not Null

–帕特里克(Patrick)
2011年1月4日,下午2:12

或@其他有关NULL与NOT NULL含义的信息,您可以参考:dba.stackexchange.com/q/63/107

–甘
2011年1月4日,11:17

#7 楼

从设计角度来看,它们也有所不同:

例如

CREATE TABLE t (
    id INTEGER  NOT NULL,
    name CHARACTER(40),
    CONSTRAINT t_PK PRIMARY KEY (id)
);

CREATE UNIQUE INDEX t_AK1 ON t (name);



看起来像:

 \d t
          Table "public.t"
 Column |     Type      | Modifiers
--------+---------------+-----------
 id     | integer       | not null
 name   | character(40) |
Indexes:
    "t_pk" PRIMARY KEY, btree (id)
    "t_ak1" UNIQUE, btree (name)



让我们插入一些数据:

op=# insert into t(id, name ) values ( 1, 'Hello');
INSERT 0 1

op=# insert into t( id, name) values ( 2, '');
INSERT 0 1

op=# insert into t( id, name) values ( 3, '');

ERROR:  duplicate key value violates unique constraint "t_ak1"



现在让我们尝试使用null:

op=# insert into t( id, name) values (4, null );

INSERT 0 1

op=# insert into t( id, name) values (5, null);

INSERT 0 1


这是允许的。

Soooooo:null既不是琐碎的字符串,也不是相反的字符串。

评论


那就是PostGres。正如其他张贴者所指出的,在Oracle中没有区别。

–汤姆·沃菲尔德
7月21日12:54

#8 楼

不得不与Oracle合作(这使您无法与众不同),我得出以下结论:


从逻辑POV上没关系。我真的想不出一个引人注目的示例,其中区分NULL和零长度字符串会在DBMS中添加任何值。
其后为:您有一个支持NULL的列,不允许零透镜''(Oracle式解决方案)或NOT NULL列允许零透镜。
根据我的经验,''在处理数据时更有意义,因为通常情况下,您希望处理不存在字符串的情况空字符串:串联,比较等。

注意:回到我的Oracle经验:假设您要
生成搜索请求的查询。如果您使用'',则只需生成WHERE columnX = <searchvalue>,它将对相等搜索起作用。如果使用NULL,则必须执行WHERE columnX=<searchvalue> or (columnX is NULL and serchvalue is NULL)。呸! :-)

#9 楼

如果我们谈论理论,那么Codd的规则就说RDBMS必须以一种特殊的方式对待NULL值。

具体如何使用取决于数据库架构师,具体取决于实际领域-任务-项目-应用-区域。

#10 楼

取决于含义。举个例子:您的专栏存储了某个人在UTC 2020年8月12日上午8点至上午9点之间所说的内容。可能是

一个人说了什么(非空字符串)
一个人什么也没说(空字符串)
您不知道一个人说了什么(空值)

通过展开(或不展开)提供给您的内容,可以使您的数据代表更方便的内容