MySQL列默认为NULL - 是样式选择,还是其他原因?

34

在许多种类的 SQL 中,有三种方式可以在每次插入行时隐式地将列设置为 NULL。它们是:

columnname type NULL
columnname type DEFAULT NULL
columnname type NULL DEFAULT NULL
第一个设置了NULL标志(与NOT NULL相对),第二个将NULL标志保留为默认值,第三个设置了NULL标志并将隐式值设置为NULL。
我听说在Microsoft SQL中,第二种变体并不完全相同,因为您还可以自定义表或模式的NULL标志的默认值。
但是对于MySQL而言,我不认为有这样的功能。此外,在MySQL中,具有NULL标志的列(与NOT NULL列不同),即使打开了严格模式,如果没有显式值,插入时始终会被隐式地设置为NULL。因此,所有这些列声明都是相同的。
在我的MySQL脚本中,对于每个NOT NULL列,我都为那些我不希望在应用程序的某些插入中设置的列指定了一个DEFAULT值,以避免在启用严格模式的情况下出现任何问题。因此,即使第三种变体最冗长和明确,我觉得选择它会更对称。像第一种或第二种变体这样的声明是否常见?
我正在考虑倾向于第二种方法,因为那是MySQL dump使用的别名,但我不确定这是否是一个好主意,因为它也将整数字面值作为列声明的默认子句中的字符串(单引号)转储。
这个问题可能看起来更像是一个具有解决方案而不是一个意见问题,但我还想了解我不知道的任何潜在陷阱。我将来可能会从MySQL迁移到PostgreSQL,我也可以使用一些来自那些专家的建议,例如PostgreSQL是否像MS-SQL一样区分这些情况。如果我有任何错误的假设,请纠正我。

2
我不确定你是否知道,在MySQL中,你可以为可空列设置一个默认值(而不是null)。如果在插入时未指定该列的值,则该列具有其默认值。你也可以明确指定要插入null,在这种情况下,该列为null。例如,你可以将一列指定为“SMALLINT DEFAULT 3”。然后,如果你显式地插入非null整数值,它会存储该值;如果你显式地插入null,则它会存储null;如果在插入时未指定值,则它会存储3,即默认值。 - Hammerite
是的!我只担心那些默认值为null的列。 - Kevin Jin
也许这个问题更适合[programmers.se]吗? - eggyal
DataGrip是一款SQL IDE,可以在您输入时提供SQL语句的自动完成功能。它提供了“所有列”版本和“最小列”版本以进行自动完成。在我使用的版本中,即使可以省略该列,但可以包含可以包含null但没有显式默认值的列在“最小列”版本中。因此,出于这个原因,我更喜欢明确指定为“NULL DEFAULT NULL”。 - allenru
2个回答

40
根据数据类型默认值的文档:
如果列可以将NULL作为值,则该列将定义为具有明确的DEFAULT NULL子句。 (我认为他们指的是隐式而不是显式)。
此外,根据CREATE TABLE语法的文档:
如果未指定NULLNOT NULL,则该列被视为已指定NULL
因此,在MySQL中,以下列定义均相同:
columnname type
columnname type NULL
columnname type DEFAULT NULL
columnname type NULL DEFAULT NULL

选择使用哪种方式需要在明确和简洁之间取得平衡。根据情况不同,我可能会使用上述任何一种方式。


12
请注意,TIMESTAMP 类型有一个特殊情况。如果你的列声明为 stamp TIMESTAMP,并且在 INSERT 时没有指定 stamp 的值,它将默认使用当前的 UTC 时间作为插入值。如果你将列声明为 stamp TIMESTAMP NULL,那么插入时将默认为 NULL。 - sam-6174

18

我遇到的每个数据库都像你所描述的那样处理NULL值。当一个列可以接受NULL值时,在INSERT操作中不提供值会将该值默认为NULL。我相信这是ANSI标准行为的一部分。

至于指定“NULL”本身,那就是个人喜好问题。标准确实说一个列允许NULL值,除非在数据定义语言的级别上指定NOT NULL。因此,NULL本身是不必要的,你有第四个等效选项:

columnname type

在ANSI标准中,NULLs已经深入嵌入到SQL语言中。你的第三个选项是最明确的,但它看起来有点不寻常。

如果你计划在整个系统中保持超级一致性,那么我会选择你所在的路径。对于每个表中的每个列都要有NULL或NOT NULL。对于所有采用默认值的列,必须使用DEFAULT语句。

然而,请不要期望你现在或将来合作的其他人会 readily follow这个例子。许多人可能会更喜欢第四个选项,因为它需要更少的键入,并且是所有(或几乎所有)SQL方言的行为方式。


1
是的。几乎没有人会编写显式的 SELECT ALL,而是使用隐式(且等效的)SELECT - ypercubeᵀᴹ
尽管eggyal提出了很好的观点(并引用了MySQL文档),但你的信息让人清楚地知道这是SQL标准,而不仅仅是MySQL标准。由于我相信如果我更改数据库系统,我不必重新访问列定义的这个特定部分,并且大多数人应该知道隐式修饰符,因此我将坚持使用你给出的最简洁的别名。谢谢! - Kevin Jin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接