什么时候使用NULL,什么时候使用空字符串?


82

我主要对MySQL和PostgreSQL感兴趣,但是您通常可以回答以下问题:

  • 是否存在逻辑上的场景,将空字符串与NULL区分会很有用?
  • 将空字符串存储为...的物理存储含义是什么?

    • 空值?
    • 空字符串?
    • 另一个领域?
    • 还有其他方法吗?

Answers:


67

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

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


2
+1很少有dba需要担心使用NULL或不使用的速度/大小的差异
Patrick

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

6
出色-未知NULL,指定了空字符串。
ScottCher 2011年

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

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

25

我不了解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时,可以表示您的设置为空,并避免使用默认设置。



17

这取决于您正在处理的域。NULL表示没有值(即没有value),而空字符串表示字符串长度为零。

例如,假设您有一个表来存储一个人的数据,并且其中包含一Gender列。您可以将值另存为“男性”或“女性”。如果用户能够选择不提供性别数据,则应将其另存为NULL(即用户未提供值),并且不要为空字符串(因为不存在带有值”的性别)。


7
如果用户选择不提供性别,则一定要存储“拒绝提供”。NULL是模棱两可的;它也可能意味着“顾客还没有被问”,“客户标识与不是我们的列表上的性别”,等等
所有交易的乔恩·

8

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

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


4
实际上不是NULL!= NULL,因为那是NULL。;-)
Peter Eisentraut 2011年

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


4

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

如果您不使用框架,或者您使用的是简单的sql语句和处理,那么无论您选择哪种方法都更容易跟踪,我都会选择哪种方法。我通常更喜欢使用NULL,这样在执行INSERT语句时就不会因为忘记将空字段设置为而感到乏味NULL


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

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

或@everyone其他有关NULL的VS NOT NULL的寓意,你可以参考这个:dba.stackexchange.com/q/63/107

2

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

  • 从逻辑POV来说没关系。我真的想不出一个引人注目的示例,其中区分NULL和零长度字符串会在DBMS中添加任何值。

  • 从中得出以下结果:您有一个NULL不允许零透镜的精干列''(Oracle-ish解决方案)或一个NOT NULL允许零透镜的列。

  • 而从我的经验,''很多串联,比较,等:在处理数据时,因为通常你想处理缺少字符串为空字符串更有意义

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


2

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

例如

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不是琐碎的字符串,也不是相反。

干杯


1

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

具体使用的方式取决于数据库架构师,具体取决于实际的域-任务-项目-应用程序-区域。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.