MySQL,最好插入NULL或空字符串?


230

我在一个网站上有一个表格,其中包含很多不同的字段。一些字段是可选的,而某些字段是必填的。在我的数据库中,我有一个表,其中包含所有这些值,是否将NULL值或空字符串插入用户未放置任何数据的DB列是更好的做法?

Answers:


220

通过使用,NULL您可以区分“不输入数据”和“不输入数据”。

更多区别:

  • 一个LENGTHNULL就是NULL,一个LENGTH空字符串的是0

  • NULLs在空字符串之前排序。

  • COUNT(message)将计算空字符串,但不计算NULLs

  • 您可以使用绑定变量搜索空字符串,但不能搜索NULL。该查询:

    SELECT  *
    FROM    mytable 
    WHERE   mytext = ?

    无论您从客户端传递的值如何,都永远不会匹配NULLin mytext。要匹配NULLs,您必须使用其他查询:

    SELECT  *
    FROM    mytable 
    WHERE   mytext IS NULL

3
但是您认为哪一个更快?0或NULL或“”
Atul Dravid 2010年

8
在InnoDB中,NULL占用的空间更少
Timo Huovinen

37
我认为这是一个好的答案,但它也完全忽略了问题的“最佳实践”要素,而只关注与切线相关的事实(NULL排序顺序和长度?这无关紧要)。在大多数输入的文本数据类型有是不是 “无应答”和“空响应”之间的差异,所以我觉得这是一个很大的问题,值得更好的答案。
尼克

6
设置UNIQUE字段时,NULL也很有效。例如,如果您有一个诸如“驾驶执照”之类的字段来添加人员的DL号,而该人员则没有。由于这是一个唯一字段,因此将添加第一个没有DL号的人,但不会添加下一个,因为它会引发唯一约束的错误。因此,NULL更好。
赛富尔·拉赫曼·莫辛

1
@Quassnoi啊,对不起...我的意思是,为什么将驾驶证号码设置为唯一是一种不好的做法?
cedbeu

44

如果您计划切换数据库,则要考虑的一件事是Oracle不支持空字符串。它们会自动转换为NULL,您不能使用诸如这样的子句查询它们WHERE somefield = ''


11
即使在您的链接上,这听起来也让我难以置信,所以我尝试了一下。空字段,设置为“”,oracle将忽略它。报告的长度为null而不是0。这是很错误的。必须有一些解决方法。认为我会将其发布为另一个问题。
史蒂夫·B。2009年

1
Steve B.:看到这个问题:stackoverflow.com/questions/1171196/…–
Quassnoi

感谢您提供参考,尽管我仍然不了解其原因。发布为stackoverflow.com/questions/1268177/...
史蒂夫B.

可能值得更新答案,以包含Quassnoi
SamuelKDavis

7
Peoplesoft(使用Oracle DB)使用单个空格表示空值。真是愚蠢。由于不允许使用0,因此它们还使用0.00025表示FTE为0。该产品做出了可爱的选择。
JP达菲(Duffy)

9

要记住的一件事是,NULL可能会使您的代码路径困难得多。例如,在Python中,大多数数据库适配器/ ORM映射NULLNone

这样的事情:

print "Hello, %(title)s %(firstname) %(lastname)!" % databaserow

可能会导致“您好,没有Joe Doe!” 为了避免这种情况,您需要类似以下代码的内容:

if databaserow.title:
    print "Hello, %(title)s %(firstname) %(lastname)!" % databaserow
else:
    print "Hello, %(firstname) %(lastname)!" % databaserow

这会使事情变得更加复杂。


25
我认为,滥用数据库来“修复”代码或框架中的错误是(非常)不好的编码习惯。如果没有数据,则应只插入NULL并保持一致。否则,您必须使用以下语句:if(myString == null || myString =“”)。当您的代码中未设置或定义对象时,您还将使用NULL而不是某种“占位符”(我认为该字符串为空)。
Gertjan

5
很大程度上取决于您选择的语言。在Python中,如果不是myString :,则测试None和“”。大概主要是文化问题。Java Guys的“坏习惯”是充满活力的人的风度。
最大

9

最好插入NULL,以确保MySQL中数据库的一致性。外键可以存储NULL为空字符串,但不能存储为空字符串。

约束中的空字符串会带来问题。您可能必须插入带有唯一空字符串的假记录,才能满足外键约束。我猜是不好的做法。

另请参阅:外键可以为NULL和/或重复吗?


约束问题过去使我感到震惊,这就是为什么我“ +1”这个答案。
HPWD

但是,如果您使用NULL,请确保您永远不会以任何空字符串结尾。易于使用许多UI技术。
调谐的

5

我不知道这是什么最佳实践,但是除非您希望null表示不同于空字符串的内容,并且用户输入与您的空字符串定义匹配,否则我通常会偏爱null。

请注意,我是说您需要定义您希望它们与众不同的方式。有时候让它们有所不同是有意义的,有时则没有。如果没有,请选择一个并坚持使用。就像我说的那样,大多数时候我倾向于使用NULL。

哦,请记住,如果该列为空,则该记录几乎不会出现在基于该列选择(在SQL术语中具有where子句)的任何查询中,除非该选择是针对空列的当然。


1
...现在,我看到了答案,我可以肯定地说,您通常关心的区别是无数据与空数据。:-)
白金天蓝色

1

如果在唯一索引中使用多个列,并且这些列中至少有一个是强制性的(即必填字段),则如果将索引中的其他列设置为NULL,则可能会出现重复的行。这是因为NULL值在唯一列中被忽略。在这种情况下,请在唯一索引的其他列中使用空字符串,以避免重复的行。

唯一索引中的列:
(event_type_id,event_title,日期,位置,网址)

示例1:
(1,'BBQ','2018-07-27',null,null)
(1,'BBQ','2018-07-27',null,null)//允许并重复。

范例2:
(1,'BBQ','2018-07-27',``,'')
(1,'BBQ','2018-07-27',``,'')//不允许重复,因为

以下是一些代码:

CREATE TABLE `test` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `event_id` int(11) DEFAULT NULL,
  `event_title` varchar(50) DEFAULT NULL,
  `date` date DEFAULT NULL,
  `location` varchar(50) DEFAULT NULL,
  `url` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `event_id` (`event_id`,`event_title`,`date`,`location`,`url`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

现在插入它以查看将允许重复的行:

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-27', NULL, NULL);

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-27', NULL, NULL);

现在插入它,并检查是否不允许:

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-28', '', '');

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-28', '', '');

因此,这里没有对与错。由您决定哪种方法最适合您的业务规则。

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.