为什么只有当create语句中存在两个或多个时间戳字段时,mysql才会抛出“字段的默认值无效”?

Mar*_* An 6 mysql timestamp default-value mysql-5.7

在 mysql 5.7.28 中我创建了一个像这样的表:

create table t1 (
id int not null,
d1 timestamp) 
engine=innodb;
Run Code Online (Sandbox Code Playgroud)

工作正常并创建d1为, 。non-nulldefault value current_timetampon update current_timestamp

但是当我尝试创建具有两个时间戳字段的相同表时,如下所示:

create table t1 (
id int not null,
d1 timestamp,
d2 timestamp) 
engine=innodb;
Run Code Online (Sandbox Code Playgroud)

我收到错误:

SQL 错误 (1067):“d2”的默认值无效

为什么只有在添加第二个时间戳字段时才会出现错误?
这是 mysql 中的错误还是某些预期行为?

小智 5

此行为在explicit_defaults_for_timestamp系统变量中进行了描述,默认情况下禁用, 5.65.7并且有效禁用5.1)并且启用8.0

\n\n

引用上面的链接:

\n\n
\n

(5.7) 如果explicit_defaults_for_timestamp被禁用,服务器将启用非标准行为并按如下方式处理 TIMESTAMP 列:

\n\n
    \n
  • 未使用 NULL 属性显式声明的 TIMESTAMP 列会自动使用 NOT NULL 属性进行声明。允许为此类列分配 NULL 值,并将该列设置为当前时间戳。
  • \n
  • 表中的第一个 TIMESTAMP 列,如果未使用 NULL 属性或显式 DEFAULT 或 ON UPDATE
    \n 属性显式声明,则自动使用 DEFAULT
    \n CURRENT_TIMESTAMP 和 ON UPDATE CURRENT_TIMESTAMP 属性进行声明。
  • \n
  • 第一个列之后的 TIMESTAMP 列,如果未使用 NULL 属性或显式 DEFAULT 属性显式声明,\n 将自动声明为 DEFAULT \'0000-00-00 00:00:00\'(\n \xe2\x80 \x9czero\xe2\x80\x9d 时间戳)。对于未为此类列指定显式值的插入行,该列将被分配“0000-00-00 00:00:00”并且不会出现警告。
  • \n
\n\n

根据是否启用严格 SQL 模式或 NO_ZERO_DATE SQL 模式,默认值“0000-00-00 00:00:00”可能无效

\n
\n\n

现在的问题5.7是该NO_ZERO_DATE模式已启用。这不允许文档中描述的默认值0000-00-00 00:00:00添加为第一个后面的时间戳列中的默认值(如果未明确声明) 。

\n\n

Mysql8.0仍然NO_ZERO_DATE启用该模式,但explicit_defaults_for_timestamp默认情况下启用环境变量,根据文档,它将添加 null 作为默认值,如下所示(这不会导致表创建时出现任何错误):

\n\n
\n

(8.0) 如果启用explicit_defaults_for_timestamp ,服务器将禁用\n非标准行为并按如下方式处理TIMESTAMP列:

\n\n

[..]

\n\n
    \n
  • 未使用 NOT NULL 属性显式声明的 TIMESTAMP 列将自动使用 NULL 属性进行声明,并允许使用 NULL 值。为此类列分配 NULL 值会将其设置为 NULL,而不是当前时间戳。
  • \n
\n\n

[..]

\n\n
    \n
  • 表中第一个 TIMESTAMP 列的处理方式与第一个 TIMESTAMP 列之后的 TIMESTAMP 列的处理方式没有区别。
  • \n
\n
\n\n

此行为也在MySQL 的问题跟踪器上进行了讨论,但已标记为“不是错误”。

\n\n

正如@Akina 在评论中提到的,不要依赖默认值。始终写下该字段的完整规范。

\n