NOT NULL意味着一个列中不能有NULL值-相反,如果在为该列插入一行时没有指定任何内容,它将使用指定的任何默认值(或者如果没有指定默认值,则使用该类型的MySQL默认值)。 不是NOT NULL的字段可能会将其值设置为NULL(本质上意味着缺少/未知/未指定的值)。NULL的行为与正常值see here for more info不同。
NOT NULL是一个列约束,当你有一个不在主键中的列时(主键本质上不是空的,所以明确地说NOT NULL是愚蠢的),你知道它的值总是已知的(不是未知的或缺失的),所以在那个列中不需要空值。 NULL是一个出现在许多上下文中的关键字-包括作为列约束,它的含义与默认值相同(即允许空值)-但也出现在许多其他上下文中,例如在INSERT...VALUES语句的一部分中插入空值。
mysql> select if(null is null, "null is null", "null is not null");
+------------------------------------------------------+
| if(null is null, "null is null", "null is not null") |
+------------------------------------------------------+
| null is null |
+------------------------------------------------------+
1 row in set (0.01 sec)
尽管大家普遍认为NOT NULL并不需要填写所有字段;它只是意味着你忽略的任何东西都将具有默认值。所以不,这并不意味着痛苦。此外,NULL在索引方面效率较低,并且在处理从查询中接收的内容时会导致许多边缘情况。 因此,虽然NULL值当然具有理论意义(在极少数情况下,您可以从中受益),但大多数情况下NOT NULL是要走的路。NOT NULL使您的字段像任何变量一样工作:它们总是有一个值,你决定这个值是否有意义。是的,如果你需要all the possible values和one extra value that tells you there's simply nothing there,你仍然可以使用NULL。
那么为什么他们如此喜欢NULL呢?
因为它是描述性的。它有一个语义意义,比如“Nnah,等等,这不仅仅是一个空字符串,这是一个更奇特的-它是lack of information!”他们会解释说“时间是00:00”和“我不知道现在是什么时间”有什么不同。这是有效的;它只是需要一些额外的努力来处理这一点。因为系统将为信息“是否有值”分配额外的空间,并且它将不断地努力检查它。因此,为了语义美的微小部分,您牺牲了时间和存储。不多,但仍然。(Instead, you could have said "99:99" which is clearly an invalid time and you can assign a constant to it. No, don't even start, it's just an example.) 整个现象让我想起了以前的isset争论,人们不知何故痴迷于看一个不存在的数组索引并得到错误消息的美丽。这完全没有意义。实用的默认值是一件幸事,它们以“你知道我的意思”的风格简化了工作,你可以写得更可读性,更简洁,更有表现力的代码,即使在你花了4年的时间在其他项目上也会有意义。
不可避免的NULL
如果你有JOIN,你迟早会遇到NULL,当你想加入另一行,但它不在那里。你必须知道你得到的不仅仅是一个空记录,它是no record at all. 否则呢?NOT NULL方便、高效,给你的惊喜也少。作为回报,它会被一些有语义强迫症的人称为无知和无耻。(这不是一件事,但应该是。)
9条答案
按热度按时间ldioqlga1#
NULL表示您不必为字段提供值...
NOT NULL表示必须为字段提供值。
例如,如果您正在为系统构建一个注册用户表,您可能希望确保user-id始终使用值(即NOT NULL)填充,但可选的配偶姓名字段可以留空(NULL)
64jmpszr2#
我建议
当空值不小心进入字段时,没有意义的NULL字段可能会引入错误。使用NOT NULL可以防止这种情况。
NULL字段最常见的原因是你有一个外键字段,它是一个“零或一”关系的选项,即不总是链接的。
如果你发现你有一个表有很多列,其中很多列都可以是NULL,这听起来像是一个反模式,考虑一下垂直分区在你的应用程序上下文中是否更有意义:)
NULL还有另一个有用的用法--将索引中的所有列设为NULL将停止为该行创建索引记录,这将优化索引;你可能只想索引行的一个非常小的子集(例如,对于一个“活动”标志只设置在1%或其他地方)-制作一个以通常为NULL的列开始的索引可以节省空间并优化该索引。
kkih6yb83#
NULL和NOT NULL有什么区别?
创建表或向表中添加列时,需要使用
NULL
或NOT NULL
指定列值可选性。NOT NULL
意味着该列的任何记录都不能有NULL
值;NULL
意味着NULL
是一个允许的值(即使列有外键约束)。因为NULL
不是一个值,你可以看到为什么有些人称之为可选性-因为数据库表要求为了有一个列,表中的每个记录都必须有一个列的示例。什么时候应该使用它们?
这是由您的业务规则决定的。
通常,您希望尽可能多的列为
NOT NULL
,因为您希望确保数据始终存在。kfgdxczn4#
NOT NULL
意味着一个列中不能有NULL
值-相反,如果在为该列插入一行时没有指定任何内容,它将使用指定的任何默认值(或者如果没有指定默认值,则使用该类型的MySQL默认值)。不是
NOT NULL
的字段可能会将其值设置为NULL
(本质上意味着缺少/未知/未指定的值)。NULL
的行为与正常值see here for more info不同。htzpubme5#
正如其他人回答的那样,
NOT NULL
只是意味着NULL
不是允许的值。然而,您总是可以选择空字符串''
(对于varchar
)或0
(对于int
)等。在使用
NOT NULL
时,一个很好的特性是,如果您忘记在INSERT
期间设置列的值,则会收到错误或警告。(假设NOT NULL
列没有DEFAULT
)允许
NULL
列的主要问题是,使用<>
(不相等)运算符永远找不到它们。=
运算符按预期工作但是,
<>
运算符将排除任何NULL
条目。这可能会导致一些细微的bug,特别是如果在测试初始化期间列没有
NULL
数据,但后来由于后续开发而添加了一些NULL
值。因此,我将所有列设置为NOT NULL
。但是,当使用
UNIQUE
KEY
/INDEX
时,允许NULL
值可能会有所帮助。通常,唯一键要求列(或列的组合)在整个表中是唯一的。唯一键是数据库将为您强制执行的一个很好的保护措施。在某些情况下,您可能希望对大多数行使用安全措施,但也有例外。
如果
UNIQUE KEY
引用的任何列是NULL
,那么该行的唯一性将不再被强制执行。显然,只有在该列上允许NULL
s时,这才有效,理解我上面解释的打嗝。如果您决定允许
NULL
值,请考虑编写<>
语句,其中包含一个附加条件来检测NULL
s。6za6bjd06#
NOT NULL
是一个列约束,当你有一个不在主键中的列时(主键本质上不是空的,所以明确地说NOT NULL
是愚蠢的),你知道它的值总是已知的(不是未知的或缺失的),所以在那个列中不需要空值。NULL
是一个出现在许多上下文中的关键字-包括作为列约束,它的含义与默认值相同(即允许空值)-但也出现在许多其他上下文中,例如在INSERT...VALUES
语句的一部分中插入空值。qgelzfjb7#
还请注意,NULL不等于任何其他值,甚至不等于NULL本身。
例如:
当你需要一个唯一的键在一个部分填充的列上时,这个NULL的定义非常有用。在这种情况下,你可以把所有的空值都保留为NULL,它不会导致任何违反唯一键的情况,因为NULL!= NULL。
下面是一个如何查看某个值是否为NULL的示例:
aelbi1ox8#
如果不确定,请使用NOT NULL。
尽管大家普遍认为NOT NULL并不需要填写所有字段;它只是意味着你忽略的任何东西都将具有默认值。所以不,这并不意味着痛苦。此外,NULL在索引方面效率较低,并且在处理从查询中接收的内容时会导致许多边缘情况。
因此,虽然NULL值当然具有理论意义(在极少数情况下,您可以从中受益),但大多数情况下NOT NULL是要走的路。NOT NULL使您的字段像任何变量一样工作:它们总是有一个值,你决定这个值是否有意义。是的,如果你需要
all the possible values
和one extra value that tells you there's simply nothing there
,你仍然可以使用NULL。那么为什么他们如此喜欢NULL呢?
因为它是描述性的。它有一个语义意义,比如“Nnah,等等,这不仅仅是一个空字符串,这是一个更奇特的-它是
lack of information!
”他们会解释说“时间是00:00”和“我不知道现在是什么时间”有什么不同。这是有效的;它只是需要一些额外的努力来处理这一点。因为系统将为信息“是否有值”分配额外的空间,并且它将不断地努力检查它。因此,为了语义美的微小部分,您牺牲了时间和存储。不多,但仍然。(Instead, you could have said "99:99" which is clearly an invalid time and you can assign a constant to it. No, don't even start, it's just an example.)
整个现象让我想起了以前的
isset
争论,人们不知何故痴迷于看一个不存在的数组索引并得到错误消息的美丽。这完全没有意义。实用的默认值是一件幸事,它们以“你知道我的意思”的风格简化了工作,你可以写得更可读性,更简洁,更有表现力的代码,即使在你花了4年的时间在其他项目上也会有意义。不可避免的NULL
如果你有JOIN,你迟早会遇到NULL,当你想加入另一行,但它不在那里。你必须知道你得到的不仅仅是一个空记录,它是
no record at all.
否则呢?NOT NULL方便、高效,给你的惊喜也少。作为回报,它会被一些有语义强迫症的人称为无知和无耻。(这不是一件事,但应该是。)
TL;DR
如果可能,首选NOT NULL。
这对机器来说也很奇怪
jq6vz3qz9#
空值是邪恶的!
好吧,我是在开玩笑,但是当NULL存在时,查询中存在严重的陷阱。例如,当将NULL与值进行比较,执行SUM或求平均值时,您需要使用COALESCE或ISNULL,否则您将得到不正确的计算,这将导致应用程序中的错误。最重要的是,COALESCE和ISNULL为查询执行添加了非常少量的时间,虽然在大多数情况下可以忽略这个额外的时间,但当查询需要在一个大表中计算许多NULL值时,这个时间可能会增加。