内容简介:当我在我们可以发现错误信息提示是时间值错误,但是我们这明显是一个合法的时间点啊。经过查询资料,发现原因是在
当我在 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
,成为了非法时间。
解决方案为:
MySQL
下面我们详细说明相关的内容。
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。
同时, DATETIME
和 TIMESTAMP
还都支持一个 6
位微秒的数据支持,格式为 YYYY-MM-DD HH:MM:SS[.fraction]
,合法范围为 .000000 - .999999
。
DATETIME
和 TIMESTAMP
还都提供自动初始化并更新为当前日期和时间的数据。
对于 TIMESTAMP
类型, MySQL
会在存储时将数据值转换为 UTC
标准时间来存储,读取时再转为当前时间。如果你的时区没有发生改变,则该值就是你存储的值,如果你改变了时区,读取到的值就会发生变化。这个特性不会对 DATETIME
生效。
查看时区
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:00
时 MySQL 会纠正为 1970-01-01 00:00:00
,而成为一个非法值。
非法时间值
对于非法的时间值,针对不同的时间类型, 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
月,为非法值。
严格模式
当我们插入非法时间值时,虽然会被纠正,但是在严格模式下,不会插入数据,反而会报错:
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
。这在处理用户输入的时候很合适,但是这个模式只对于 DATE
和 DATETIME
很合适,对于 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)
总结
对于这种问题,有两种解决方法:
MySQL
参考资料
- 11.3.1 The DATE, DATETIME, and TIMESTAMP Types: https://dev.mysql.com/doc/ref...
- 5.1.13 MySQL Server Time Zone Support: https://dev.mysql.com/doc/ref...
- 5.1.11 Server SQL Modes: https://dev.mysql.com/doc/ref...
以上所述就是小编给大家介绍的《MySQL时间类型和模式》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
ANSI Common Lisp
Paul Graham / Prentice Hall / 1995-11-12 / USD 116.40
For use as a core text supplement in any course covering common LISP such as Artificial Intelligence or Concepts of Programming Languages. Teaching students new and more powerful ways of thinking abo......一起来看看 《ANSI Common Lisp》 这本书的介绍吧!