2017-07-20 BoobooWei
TIMESTAMP在MySQL5.5中的行为
时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。通俗的讲, 时间戳是一份能够表示一份数据在一个特定时间点已经存在的完整的可验证的数据。
- 第一个未设置默认值的TIMESTAMP NOT NULL字段隐式默认值:
CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP - 后面未设置默认值的TIMESTAMP NOT NULL字段隐式默认值:
0000-00-00 00:00:00 - TIMESTAMP NOT NULL字段插入NULL时,会使用隐式默认值:
CURRENT_TIMESTAMP - 不支持多个CURRENT_TIMESTAMP 默认值
table | insert | select | |
---|---|---|---|
create db1.t1 (id int,created timestamp); | insert db1.t1 set id=1; | 2017-07-20 13:16:25 | |
create db1.t2 (id int,created timestamp not null); | insert db1.t2 set id=1; | 2017-07-20 13:16:29 | |
create db1.t3 (id int,created timestamp not null default ‘0000-00-00 00:00:00’); | insert db1.t3 set id=1; | 0000-00-00 00:00:00 | |
create db1.t4 (id int,created timestamp not null,modifed not null); | insert db1.t4 set id=1; | 2017-07-20 13:16:35 \ | 0000-00-00 00:00:00 |
MariaDB [db1]> create table db1.t1 (id int,created timestamp); |
TIMESTAMP在MySQL5.6中的行为
支持多个CURRENT_TIMESTAMP 默认值
可以兼容5.5的行为,支持隐性默认值
explicit_defaults_for_timestamp=0
在5.6.6及以后的版本中,如果在配置文件中没有指定explicit_defaults_for_timestamp参数,启动时error日志中会报如下错误
[Warning] TIMESTAMP with implicit DEFAULT value is deprecated.
Please use --explicit_defaults_for_timestamp server option (see
documentation for more details).
可以去掉隐性默认值 explicit_defaults_for_timestamp=1
- 如果我们在启动的时候在配置文件中指定了explicit_defaults_for_timestamp=1,mysql会按照如下的方式处理TIMESTAMP 列
- 此时如果TIMESTAMP列没有显式的指定not null属性,那么默认的该列可以为null,此时向该列中插入null值时,会直接记录null,而不是current timestamp。
- 不会自动的为表中的第一个TIMESTAMP列加上
DEFAULT CURRENT_TIMESTAMP
和ON UPDATE CURRENT_TIMESTAMP属性,除非你在建表的时候显式的指明- 如果TIMESTAMP列被加上了not null属性,并且没有指定默认值。这时如果向表中插入记录,但是没有给该TIMESTAMP列指定值的时候,如果strict sql_mode被指定了,那么会直接报错。如果strict sql_mode没有被指定,那么会向该列中插入’0000-00-00 00:00:00’并且产生一个warning
- explicit_defaults_for_timestamp参数主要用来控制TIMESTAMP数据类型跟其他数据类型不一致的特性,但是TIMESTAMP的这个特性在将来会被废弃,所以explicit_defaults_for_timestamp参数也会在将来被废弃
测试结果
设置sql_mode不跳过该错误
mysql> select @@sql_mode; |
explicit_defaults_for_timestamp=0 | insert | select | |
---|---|---|---|
create table t1 (id int,created timestamp); | insert db1.t1 set id=1; | 2017-07-20 14:23:16 | |
create table t2 (id int,created timestamp not null); | insert db1.t2 set id=1; | 2017-07-20 14:23:20 | |
create table t3 (id int,created timestamp not null default ‘0000-00-00 00:00:00’); | error | ||
create table t4 (id int,created timestamp not null,modifed timestamp not null); | error | ||
create table db1.t3 (id int,created timestamp not null default ‘2017-10-01 00:00:00’); | insert db1.t3 set id=1; | 2017-10-01 00:00:00 | |
create table db1.t4 (id int,created timestamp not null,modified timestamp not null default ‘2017-10-01 00:00:00’); | insert db1.t4 set id=1; | 2017-07-20 14:23:25 \ | 2017-10-01 00:00:00 |
select @@explicit_defaults_for_timestamp; |
explicit_defaults_for_timestamp=1 | insert | select | |
---|---|---|---|
create table t1 (id int,created timestamp); | insert db1.t1 set id=1; | NULL | |
create table t2 (id int,created timestamp not null); | insert db1.t2 set id=1; | error | |
create table t3 (id int,created timestamp not null default ‘0000-00-00 00:00:00’); | error | ||
create table t3 (id int,created timestamp not null default ‘2017-10-01 00:00:00’); | insert db1.t3 set id=1; | 2017-10-01 00:00:00 | |
create table t4 (id int,created timestamp not null,modified timestamp not null); | insert db1.t4 set id=1; | error |
select @@explicit_defaults_for_timestamp; |
设置sql_mode跳过该错误
set @@sql_mode=''; |
explicit_defaults_for_timestamp=0 | insert | select | |
---|---|---|---|
create table t1 (id int,created timestamp); | insert db1.t1 set id=1; | NULL | |
create table t2 (id int,created timestamp not null); | insert db1.t2 set id=1; | 0000-00-00 00:00:00 | |
create table t3 (id int,created timestamp not null default ‘0000-00-00 00:00:00’); | insert db1.t3 set id=1; | 0000-00-00 00:00:00 | |
create table t4 (id int,created timestamp not null,modified timestamp not null); | insert db1.t4 set id=1; | 0000-00-00 00:00:00 \ | 0000-00-00 00:00:00 |
set @@sql_mode=''; |
explicit_defaults_for_timestamp=1 | insert | select | |
---|---|---|---|
create table t1 (id int,created timestamp); | insert db1.t1 set id=1; | NULL | |
create table t2 (id int,created timestamp not null); | insert db1.t2 set id=1; | 0000-00-00 00:00:00 | |
create table t3 (id int,created timestamp not null default ‘0000-00-00 00:00:00’); | insert db1.t3 set id=1; | 0000-00-00 00:00:00 | |
create table t4 (id int,created timestamp not null,modifed timestamp not null); | insert db1.t4 set id=1; | 0000-00-00 00:00:00 \ | 0000-00-00 00:00:00 |
set explicit_defaults_for_timestamp=1; |
测试总结
SQL | MySQL版本 | explicit_defaults_for_timestamp | sql_mode | select | |
---|---|---|---|---|---|
created timestamp | 5.5 | 无该参数 | 开启 | current_timestamp()插入时的系统时间 | |
5.6 | 0 | 开启 | current_timestamp()插入时的系统时间 | ||
5.6 | 1 | 开启 | NULL | ||
5.6 | 0 | 关闭 | NULL | ||
5.6 | 1 | 关闭 | NULL | ||
created timestamp not null | 5.5 | 无该参数 | 开启 | current_timestamp()插入时的系统时间 | |
5.6 | 0 | 开启 | current_timestamp()插入时的系统时间 | ||
5.6 | 1 | 开启 | error 需要强制插入大于1970年的日期 | ||
5.6 | 0 | 关闭 | 0000-00-00 00:00:00 | ||
5.6 | 1 | 关闭 | 0000-00-00 00:00:00 | ||
created timestamp not null default ‘0000-00-00 00:00:00’ | 5.5 | 无该参数 | 开启 | 设定的默认值 0000-00-00 00:00:00 | |
5.6 | 0 | 开启 | error 需要强制指定大于1970年的日期 | ||
5.6 | 1 | 开启 | error 需要强制指定大于1970年的日期 | ||
5.6 | 0 | 关闭 | 0000-00-00 00:00:00 | ||
5.6 | 1 | 关闭 | 0000-00-00 00:00:00 | ||
created timestamp not null,modified timestamp not null | 5.5 | 无该参数 | 开启 | 2017-07-20 13:16:35 \ | 0000-00-00 00:00:00 |
5.6 | 0 | 开启 | created列为current_timestamp()即插入时的系统时间;modified列需要强制设置默认值为大于1970年的日期 | ||
5.6 | 1 | 开启 | created列为current_timestamp()即插入时的系统时间;modified列需要强制插入默认值为大于1970年的日期 | ||
5.6 | 0 | 关闭 | 0000-00-00 00:00:00 | ||
5.6 | 1 | 关闭 | 0000-00-00 00:00:00 |
MySQL 5.5 自己的总结
- timestamp默认不会为NULL,所以not null设与不设置都是一样的;
- 如果用户插入记录时timestamp的列没有插入值,则默认为当前系统的时间,或者为用户自定义的default时间;
- 用户自定义的default时间可以是
0000-00-00 00:00:00
。
MySQL 5.6 自己的总结
5.6和5.5的timestamp表示范围
| 版本 | timestamp范围 | default | sql_mode关闭 |
| —— | ———————————————————— | ———————————————————- | —————————- |
| 5.5 | 1970-01-01 00:00:00 到 2037-12-31 23:59:59 | 0000-00-00 00:00:00 | |
| 5.6 | 1970-01-01 00:00:00 到 2037-12-31 23:59:59 | NULL(explicit_defaults_for_timestamp=1) | 0000-00-00 00:00:00 |新增explicit_defaults_for_timestamp参数
如果用户插入记录时timestamp的列没有插入值,则情况入下表:
| explicit_defaults_for_timestamp | created timestatmp | created timestamp not null |
| ———————————————- | ————————— | ————————————— |
| 0(默认) | 当前系统的时间 | 当前系统的时间 |
| 1 | NULL | error 需要强制插入大于1970年的日期 |可以观察到,当该参数的值使用默认的0时,与5.5的情况是相同的。
用户设定的default时间不可以是
0000-00-00 00:00:00
,除非关闭sql_mode;
insert into t3 set id=4,created='2037-12-31 23:59:59'; |