MySQL时间类型和模式详情

 更新时间:2021年09月26日 10:45:44   作者:赵帅强  
这篇文章主要介绍MySQL时间类型和模式 MySQL会在存储时将数据值转换为UTC标准时间来存储,读取时再转为当前时间。如果你的时区没有发生改变,则该值就是你存储的值,如果你改变了时区,读取到的值就会发生变化。这个特性不会对DATETIME生效,需要的朋友可以参考一下

当我在MySQL数据库中尝试插入一条带有时间戳的数据时报错:

mysql> insert into alarm_service values (6, '1970-01-01 08:00:00'); 
ERROR 1292 (22007): Incorrect datetime value: '1970-01-01 08:00:00' for column 'time' at row 1

# 查看表结构
mysql> show create table alarm_service;
+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table         | Create Table                                                                                                                                                                                                                         |
+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| alarm_service | CREATE TABLE `alarm_service` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 |
+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

我们可以发现错误信息提示是时间值错误,但是我们这明显是一个合法的时间点啊。

经过查询资料,发现原因是在MySQL中,timestamp类型的合法区间是1970-01-01 00:00:01 - 2038-01-19 03:14:07 UTC,而在存储是,会先将你插入的数据转换为UTC时间,然后存储起来,读取的时候,再转换为你的本地时间。由于我的时区为东八区,因此转换后就变为了1970-01-01 00:00:00 UTC,成为了非法时间。

解决方案为:

  1. 调整时间为合法范围
  2. 调整MySQL严格模式,允许非法时间

下面我们详细说明相关的内容。

1、MySQL时间类型

MySQL时间类型分为三种:

  • DATE:用于只包含日期不包含时间的时候,MySQL会将格式转换为YYYY-MM-DD,合法范围为1000-01-01 - 9999-12-31
  • DATETIME:用于包含日期+时间的时候,格式为YYYY-MM-DD HH:MM:SS,合法范围为1000-01-01 00:00:00 - 9999-12-31 23:59:59
  • TIMESTAMP:用于包含日期+时间的时候,格式为YYYY-MM-DD HH:MM:SS,合法范围为1997-01-01 00:00:01 - 2038-01-19 03:14:07 UTC

同时,DATETIMETIMESTAMP还都支持一个6位微秒的数据支持,格式为YYYY-MM-DD HH:MM:SS[.fraction] ,合法范围为.000000 - .999999

DATETIMETIMESTAMP还都提供自动初始化并更新为当前日期和时间的数据。

对于TIMESTAMP类型,MySQL会在存储时将数据值转换为UTC标准时间来存储,读取时再转为当前时间。如果你的时区没有发生改变,则该值就是你存储的值,如果你改变了时区,读取到的值就会发生变化。这个特性不会对DATETIME生效。

2、查看时区

mysql> show variables like '%zone%';                                       
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone | CST    |
| time_zone        | SYSTEM |
+------------------+--------+


可以看到当前设置的时区是SYSTEM,即跟操作系统保持一致,同时系统的时区是CST(China Standard Time 北京标准时间),查看系统时间也可以看到是东8区(+0800):

$ date -R
Tue, 23 Apr 2019 11:22:47 +0800


因此我们输入1970-01-01 08:00:00MySQL会纠正为1970-01-01 00:00:00,而成为一个非法值。

3、非法时间值

对于非法的时间值,针对不同的时间类型,MySQL会将其转为合适的值:0000-00-00 0000-00-00 00:00:00

比如月份为1-12月,当你尝试插入2019-13-01 00:00:00时,就会被纠正为0000-00-00 00:00:00,因为不存在13月,为非法值。

4、严格模式

当我们插入非法时间值时,虽然会被纠正,但是在严格模式下,不会插入数据,反而会报错:

ERROR 1292 (22007): Incorrect datetime value: '1970-01-01 08:00:00' for column 'time' at row 1


我们可以通过设置模式,来调整MySQL的行为,首先查看MySQL的模式:

mysql> show variables like '%sql_mode%';            
+----------------------------+--------------------------------------------+
| Variable_name              | Value                                      |
+----------------------------+--------------------------------------------+                               |
| sql_mode                   | STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION |
+----------------------------+--------------------------------------------+


在这个模式下,非法时间会直接报错,我们可以调整模式为ALLOW_INVALID_DATES

mysql> set session sql_mode = 'ALLOW_INVALID_DATES';
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like '%sql_mode%';            
+---------------+---------------------+
| Variable_name | Value               |
+---------------+---------------------+
| sql_mode      | ALLOW_INVALID_DATES |
+---------------+---------------------+
1 row in set (0.00 sec)

在这个模式下,不会再完备检查日期的合法性,只会检查月份的范围在1-12,日期在1-31。这在处理用户输入的时候很合适,但是这个模式只对于DATEDATETIME很合适,对于TIMESTAMP,依然需要一个合法的值,否则就会纠正为0000-00-00 00:00:00。

在非法值时,如果这个模式启用,就会报错;如果禁用,就会纠正为0000-00-00 00:00:00并产生一个警告:

mysql> insert into alarm_service values (7, '1970-01-01 08:00:00'); 
Query OK, 1 row affected, 1 warning (0.00 sec)

总结:

对于这种问题,有两种解决方法:

  1. 调整时间为合法范围
  2. 调整MySQL严格模式,允许非法时间

5、case汇总

ERROR 1067 (42000): Invalid default value for 'createTime'

查看原因发现设置为:

# 查看创建表单的语句
CREATE TABLE `dimensionsConf` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `createTime` datetime DEFAULT CURRENT_TIMESTAMP,
) ENGINE=InnoDB AUTO_INCREMENT=178 DEFAULT CHARSET=utf8;

# 查看数据库版本
$mysql --version
mysql  Ver 14.14 Distrib 5.1.30, for unknown-linux-gnu (x86_64) using  EditLine wrapper

到此这篇关于MySQL时间类型和模式详情的文章就介绍到这了,更多相关MySQL时间类型和模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL中几种插入和批量语句实例详解

    MySQL中几种插入和批量语句实例详解

    这篇文章主要给大家介绍了关于MySQL中几种插入和批量语句的相关资料,在mysql数据库中,实现批量插入数据与批量更新数据的例子,即批量insert、update的方法,需要的朋友可以参考下
    2021-09-09
  • mysql 5.7.13 解压缩版(免安装)安装配置教程

    mysql 5.7.13 解压缩版(免安装)安装配置教程

    这篇文章主要介绍了MySQL 5.7.13 for Windows解压缩版(免安装)安装配置教程,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • mysql 5.7.11 winx64安装配置教程

    mysql 5.7.11 winx64安装配置教程

    这篇文章主要介绍了mysql 5.7.11 winx64安装配置教程,介绍了MySQL5.7安装及初始化,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • 深入探索数据库MySQL性能优化与复杂查询相关操作

    深入探索数据库MySQL性能优化与复杂查询相关操作

    数据库MySQL 是一种开源的关系型数据库管理系统,在进行 MySQL 数据库开发过程中,需要深入了解如何进行性能优化和复杂查询,以提高系统的效率和可靠性,本文介绍的非常详细,需要的朋友可以参考一下
    2023-04-04
  • 一篇文章带你了解MySQL数据库约束

    一篇文章带你了解MySQL数据库约束

    数据库中要管理很多数据,但是这些数据是否正确、是否非法,光靠人力来检验是远远不够的,因此我们想让数据库拥有丰富的检验和校验能力,所以便引入了约束,下面这篇文章主要给大家介绍了关于MySQL数据库约束的相关资料,需要的朋友可以参考下
    2023-06-06
  • 在centOS 7安装mysql 5.7的详细教程

    在centOS 7安装mysql 5.7的详细教程

    这篇文章主要介绍了在centOS 7安装mysql 5.7的详细教程,非常不错,具有参考借鉴价值,需要的朋友参考下吧
    2016-12-12
  • MySQL报错:Starting MySQL ERROR! Couldn‘t find MySQL server (/usr/local/mysql/bin/mysqld_safe)

    MySQL报错:Starting MySQL ERROR! Couldn‘t f

    本文主要介绍了MySQL报错:Starting MySQL ERROR! Couldn‘t find MySQL server (/usr/local/mysql/bin/mysqld_safe)
    2024-03-03
  • mysql分表程序改动方法

    mysql分表程序改动方法

    在本篇文章里小编给大家分享了关于mysql分表程序改动方法以及相关知识点,需要的朋友们跟着学习下。
    2019-04-04
  • Mysql删除重复数据通用SQL的两种方法

    Mysql删除重复数据通用SQL的两种方法

    本文主要介绍了Mysql删除重复数据通用SQL的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-08-08
  • InnoDB的关键特性-插入缓存,两次写,自适应hash索引详解

    InnoDB的关键特性-插入缓存,两次写,自适应hash索引详解

    下面小编就为大家带来一篇InnoDB的关键特性-插入缓存,两次写,自适应hash索引详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03

最新评论