将空字符串存储为...的物理存储含义是什么?
NULL?
空字符串?
另一个字段?
还有其他方法吗?
#1 楼
假设记录来自表单以收集姓名和地址信息。如果用户不住在公寓里,那么地址的第2行通常为空白。在这种情况下,空字符串是完全有效的。我倾向于使用NULL来表示该值未知或未给出。我不认为实际中的物理存储差异值得担心。作为数据库管理员,我们还有很多要炸的鱼!
#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点之间所说的内容。可能是一个人说了什么(非空字符串)
一个人什么也没说(空字符串)
您不知道一个人说了什么(空值)
通过展开(或不展开)提供给您的内容,可以使您的数据代表更方便的内容
评论
+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