Answers:
假设记录来自表单以收集姓名和地址信息。如果用户不住在公寓里,那么地址的第2行通常为空白。在这种情况下,空字符串是完全有效的。我倾向于使用NULL来表示该值未知或未给定。
我不认为实际中的物理存储差异值得担心。作为数据库管理员,我们还有很多要炸的鱼!
我不了解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时,可以表示您的设置为空,并避免使用默认设置。
值得牢记的一件事是,当您有一个不需要的字段,但是存在的任何值必须唯一时,将需要您将空值存储为NULL。否则,您将只能在该字段中使用一个元组且其值为空。
关系代数和NULL值也有一些区别:例如NULL!= NULL。
UNIQUE
约束。幸运的是,从2008年开始,您可以使用过滤索引来获得正确的行为。
您可能还会考虑Date对NULL的评论以及SQL和关系理论中的3VL问题(以及Rubinson对Date的评论,空值,三值逻辑和SQL中的歧义的评论:对Date的评论)。
两者在相关的SO线程中都有详细的参考和讨论,从数据库模型中消除可空列的选项。
一个新的想法,对NULL
/ 的选择产生很大影响NOT NULL
是,如果您正在使用框架。我大量使用symfony,使用允许NULL
字段可简化处理数据时的某些代码和数据检查。
如果您不使用框架,或者您使用的是简单的sql语句和处理,那么无论您选择哪种方法都更容易跟踪,我都会选择哪种方法。我通常更喜欢使用NULL,这样在执行INSERT
语句时就不会因为忘记将空字段设置为而感到乏味NULL
。
不得不与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)
。呸! :-)
从设计角度来看,它们也有所不同:
例如
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不是琐碎的字符串,也不是相反。
干杯
NULL
或不使用的速度/大小的差异