首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么MySQL 5.7时间戳不为空需要默认值?

为什么MySQL 5.7时间戳不为空需要默认值?
EN

Database Administration用户
提问于 2022-07-27 06:28:47
回答 2查看 2.4K关注 0票数 2

当我试图创建一个具有非空时间戳的表时,它要求我向它添加一个默认的时间戳,或者使用隐式缺省。但我不知道为何要这样做。

看看https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=c615bce0cd1009b0c597593e73fdd794

其中,以下SQL

代码语言:javascript
复制
create table t3 (
id int not null,
d1 timestamp not null,
num double not null)
engine=innodb;

将被转化为

代码语言:javascript
复制
CREATE TABLE `t3` (
  `id` int(11) NOT NULL,
  `d1` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `num` double NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1

在使用这些工具时,我们可以清楚地看到int和double不会自动为其生成默认值,但是时间戳会自动生成默认值。为什么时间戳需要默认,而另一个则不需要?

就我个人而言,我希望没有默认情况,当最终用户在没有d1时间戳的情况下向行中插入数据时,就会抛出一个异常,这样的行将无法注入到表中。但很明显,这似乎并不是MySQL所采取的想法。

EN

回答 2

Database Administration用户

发布于 2022-07-27 07:45:53

它在显式_默认值_为_时间戳上特别提到。

如果禁用explicit_defaults_for_timestamp,服务器将启用非标准行为并按以下方式处理时间戳列:表中的第一个时间戳列(如果没有显式声明为NULL属性或显式默认或UPDATE属性)将自动使用默认CURRENT_TIMESTAMP和UPDATE CURRENT_TIMESTAMP属性声明。

此行为仅发生在禁用explicit_defaults_for_timestamp时的第一个时间戳列。

代码语言:javascript
复制
mysql> select version();
+-----------------------------+
| version()                   |
+-----------------------------+
| 5.7.16-0ubuntu0.16.04.1-log |
+-----------------------------+

mysql> show variables like "%explicit_defaults_for_timestamp%";
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| explicit_defaults_for_timestamp | OFF   |
+---------------------------------+-------+
    
mysql> create table t3 (
    -> id int not null,
    -> d1 timestamp not null,
    -> d2 timestamp not null,
    -> num double not null)
    -> engine=innodb;
Query OK, 0 rows affected (0.31 sec)

mysql> show create table t3;

  CREATE TABLE `t3` (
  `id` int(11) NOT NULL,
  `d1` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `d2` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `num` double NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1  

如问题所示

在使用这些工具时,我们可以清楚地看到int和double不会自动为其生成默认值,但是时间戳会自动生成默认值。为什么时间戳需要默认,而另一个则不需要?

MySQL处理时间戳的方式与其他数据类型不同。

就我个人而言,我希望没有默认情况,并且当最终用户在没有d1时间戳的情况下向行中插入数据时

这可以通过启用explicit_defaults_for_timestamp来完成。

代码语言:javascript
复制
mysql> set session explicit_defaults_for_timestamp = 1;
Query OK, 0 rows affected (0.00 sec)

mysql> show session variables like "%explicit_defaults_for_timestamp%";
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| explicit_defaults_for_timestamp | ON    |
+---------------------------------+-------+
1 row in set (0.00 sec)

mysql> drop table t3;
Query OK, 0 rows affected (0.09 sec)

mysql> create table t3 (
    -> id int not null,
    -> d1 timestamp not null,
    -> num double not null)
    -> engine=innodb;
Query OK, 0 rows affected (0.18 sec)

mysql> show create table t3;

 CREATE TABLE `t3` (
  `id` int(11) NOT NULL,
  `d1` timestamp NOT NULL,
  `num` double NOT NULL
  ) ENGINE=InnoDB DEFAULT CHARSET=latin1 
1 row in set (0.00 sec)
票数 4
EN

Database Administration用户

发布于 2022-07-28 16:18:06

)Ergest很好地讨论了事情的进展。我来说明原因。)

为什么?这是一个古老的“特征”。突然删除该特性将导致迁移问题。

在过去的20多年前,DEFAULT值主要是由MySQL提供的,而不是明确提供的。特别是,根据定义,TIMESTAMP没有指定它就给出了DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

注意:这是隐式DEFAULT中唯一不是常量的情况。(好的,AUTO_INCREMENT是另一个。)

后来,当允许DEFAULT采用更复杂的语法时,设计人员需要决定如何处理从旧版本升级的数据库。这导致了像explicit_defaults_for_timestamp这样笨拙的事情作为一种妥协。

票数 1
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/314898

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档