简介: explicit_defaults_for_timestamp
系统变量决定MySQL服务端对timestamp列中的默认值和NULL
值的不一样处理方法。此变量自MySQL 5.6.6 版本引入,分为全局级别和会话级别,可动态更新,默认值为OFF。本文主要介绍该参数打开和关闭状况下对timestamp的影响 。mysql
当该参数默认设置为OFF时,其行为以下:sql
下面咱们来测试下:(本文操做基于MySQL5.7.23 版本 SQL_MODE不包含'NO_ZERO_DATE')测试
mysql> show variables like 'explicit_defaults_for_timestamp'; +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | explicit_defaults_for_timestamp | OFF | +---------------------------------+-------+ mysql> create table t1 -> ( -> ts1 timestamp, -> ts2 timestamp, -> ts3 timestamp default '2010-01-01 00:00:00' -> ); Query OK, 0 rows affected (0.03 sec) mysql> show create table t1\G *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( `ts1` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `ts2` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `ts3` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) mysql> insert into t1 values (null,null,null); Query OK, 1 row affected (0.00 sec) mysql> select * from t1; +---------------------+---------------------+---------------------+ | ts1 | ts2 | ts3 | +---------------------+---------------------+---------------------+ | 2019-04-09 15:54:56 | 2019-04-09 15:54:56 | 2019-04-09 15:54:56 | +---------------------+---------------------+---------------------+ 1 row in set (0.00 sec)
从表结构来看,MySQL自动为第一个timestamp字段自动设置NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP属性,然后面的timestamp字段,若没有指定,则设置了 NOT NULL DEFAULT '0000-00-00 00:00:00'属性。若是向timestamp这个列中插入null值,系统会自动的设置该列的值为current timestamp值。即explicit_defaults_for_timestamp=OFF时,即便timestamp列设为NOT NULL也能插入NULL值,系统会自动将NULL值设为current timestamp。code
当该参数设置为ON时,其行为以下:ci
一样的,咱们来测试下:rem
mysql> show variables like 'explicit_defaults_for_timestamp'; +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | explicit_defaults_for_timestamp | ON | +---------------------------------+-------+ mysql> create table t2 -> ( -> ts1 timestamp, -> ts2 timestamp, -> ts3 timestamp default '2010-01-01 00:00:00' -> ); Query OK, 0 rows affected (0.02 sec) mysql> show create table t2\G *************************** 1. row *************************** Table: t2 Create Table: CREATE TABLE `t2` ( `ts1` timestamp NULL DEFAULT NULL, `ts2` timestamp NULL DEFAULT NULL, `ts3` timestamp NULL DEFAULT '2010-01-01 00:00:00' ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.01 sec) mysql> insert into t2 values (null,null,null); Query OK, 1 row affected (0.01 sec) mysql> select * from t2; +------+------+------+ | ts1 | ts2 | ts3 | +------+------+------+ | NULL | NULL | NULL | +------+------+------+ 1 row in set (0.00 sec) -- 指定NOT NULL mysql> create table t3 -> ( -> ts1 timestamp, -> ts2 timestamp, -> ts3 timestamp not null -> ); Query OK, 0 rows affected (0.01 sec) mysql> show create table t3\G *************************** 1. row *************************** Table: t3 Create Table: CREATE TABLE `t3` ( `ts1` timestamp NULL DEFAULT NULL, `ts2` timestamp NULL DEFAULT NULL, `ts3` timestamp NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.01 sec) mysql> insert into t3 values (null,null,null); ERROR 1048 (23000): Column 'ts3' cannot be null mysql> insert into t3 (ts1,ts2) values (null,null); Query OK, 1 row affected, 1 warning (0.01 sec) mysql> show warnings; +---------+------+------------------------------------------+ | Level | Code | Message | +---------+------+------------------------------------------+ | Warning | 1364 | Field 'ts3' doesn't have a default value | +---------+------+------------------------------------------+ mysql> select * from t3; +------+------+---------------------+ | ts1 | ts2 | ts3 | +------+------+---------------------+ | NULL | NULL | 0000-00-00 00:00:00 | +------+------+---------------------+
从表结构上看出,在参数开启的状况下MySQL默认会为timestamp列添加 null default null属性,并且MySQL也没有为第一个timestamp字段设置该列为current timestamp值。timestamp 字段写入null值,写入以后存储的就是null值,而不是当前的时间。当timestamp 字段指定NOT NULL时,若显式插入NULL则报错提示:该字段不能为空;若不显式插入该字段且SQL_MODE不包含'NO_ZERO_DATE',则会向该列中插入'0000-00-00 00:00:00'而且产生一个warning。get
总结:it
实际状况下,咱们常常会这样建立表:table
CREATE TABLE `table_name` ( `increment_id` INT UNSIGNED NOT NULL auto_increment COMMENT '自增主键', ... `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`increment_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
此时timestamp字段会指定NOT NULL,这时建议explicit_defaults_for_timestamp
参数采用默认的OFF,这样当timestamp字段显式插入NULL值时不报错,特别是程序sql写的不规范时,能够避免程序插入报错。class
在不一样环境间,此参数建议统一 ,否则可能出现程序在这个环境运行正常 在另一个环境却出现报错的状况。笔者了解到亚马逊RDS MySQL5.7实例该参数默认为ON,在环境迁移时要特别注意下该参数。