当我试图创建一个具有非空时间戳的表时,它要求我向它添加一个默认的时间戳,或者使用隐式缺省。但我不知道为何要这样做。
看看https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=c615bce0cd1009b0c597593e73fdd794,
其中,以下SQL
create table t3 (
id int not null,
d1 timestamp not null,
num double not null)
engine=innodb;将被转化为
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所采取的想法。
发布于 2022-07-27 07:45:53
它在显式_默认值_为_时间戳上特别提到。
如果禁用explicit_defaults_for_timestamp,服务器将启用非标准行为并按以下方式处理时间戳列:表中的第一个时间戳列(如果没有显式声明为NULL属性或显式默认或UPDATE属性)将自动使用默认CURRENT_TIMESTAMP和UPDATE CURRENT_TIMESTAMP属性声明。
此行为仅发生在禁用explicit_defaults_for_timestamp时的第一个时间戳列。
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来完成。
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)发布于 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这样笨拙的事情作为一种妥协。
https://dba.stackexchange.com/questions/314898
复制相似问题