MySQL时间加减的正确打开方式
1背景介绍
业务会有这样的需求:时间字段需要加1或减1秒。 研发sql:update table set time = time + 1 where id=1; 看似好像挺对的,但是偶尔会出现不是想要的结果。
2模拟测试
新建一个表test1,有3条记录如下,执行+1操作:
CREATE TABLE `test1` (
`Id` bigint(20) NOT NULL AUTO_INCREMENT,
`Type` smallint(6) DEFAULT '0',
`Status` smallint(6) DEFAULT '0',
`CreateTime` datetime DEFAULT NULL,
`ModifyTime` timestamp DEFAULT NULL,
PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
> select CreateTime,ModifyTime from test1;
+-+-------------+-------------+
| Id | CreateTime | ModifyTime |
+-+-------------+-------------+
| 1 | 2017-08-01 18:30:59 | 2017-08-01 18:30:59 |
| 2 | 2017-08-01 18:31:01 | 2017-08-01 18:31:01 |
| 3 | 2017-08-01 18:31:02 | 2017-08-01 18:31:02 |
+-+-------------+-------------+
> update test1 set CreateTime=CreateTime+1,ModifyTime=ModifyTime+1;
> select * from test1;
+-+-------------+-------------+
| Id | CreateTime | ModifyTime |
+-+-------------+-------------+
| 1 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
| 2 | 2017-08-01 18:31:02 | 2017-08-01 18:31:02 |
| 3 | 2017-08-01 18:31:03 | 2017-08-01 18:31:03 |
+-+-------------+-------------+
测试后我们看到59秒的时候加1秒全部变成了0000-00-00 00:00:00,而其他是正确的,此时我们会觉得是不是跟逢整进位有关系,59秒的时候再加上1秒进位1分钟,结果却变成了0000-00-00 00:00:00,这是为什么?
继续测试:
> update test1 set CreateTime=CreateTime+55,ModifyTime=ModifyTime+105;
> select CreateTime,ModifyTime from test1;
+---------------------+---------------------+
| CreateTime | ModifyTime |
+---------------------+---------------------+
| 0000-00-00 00:00:00 | 2000-01-05 00:00:00 |
| 2017-08-01 18:31:57 | 2017-08-01 18:32:07 |
| 2017-08-01 18:31:58 | 2017-08-01 18:32:08 |
+---------------------+---------------------+
CreateTime+55,ModifyTime+105后,并不是我们想的逢整进位的关系。
3问题分析
> select ModifyTime from test1 limit 1;
+----------------+
| ModifyTime |
+----------------+
| 2017-08-01 18:30:59 |
+----------------+
> update test1 set ModifyTime = ModifyTime + <n>;
其实只要我们知道datatime类型以'YYYY-MM-DD HH:MM:SS'的形式来显示的,就知道原因了。 例如: n=61,会转换成 '0000-00-00 00-00-61'; n=101,会转换成 '0000-00-00 00-01-01'; n=65535,会转换成 '0000-00-00 06-55-35'; 因为秒只能是0~59,不会有大于59秒的时候存在,如果大于59属于异常,会初始化成'0000-00-00 00-00-00'状态。分钟也一样。 所以如果此时秒正好为0: 当1<=n<60时,可以正常相加; 当60<=n<100时,超过59秒属于异常,初始化成'0000-00-00 00-00-00'; 当n=100时,会转换成 '0000-00-00 00-01-00',也就是1分钟,如果此时为59分,也会初始化成'0000-00-00 00-00-00'; 以此类推,所以并不是所有的都会成功,也不是所有的都会失败,因为这种方式本来就不符合时间加减规范,其他日期类型同理。 所以要杜绝此类问题,研发就不能偷懒,必须使用时间函数。
4正确方式
为日期加上一个时间间隔:date_add() date_add(@dt, interval 1 microsecond); -加1毫秒 date_add(@dt, interval 1 second); -加1秒 date_add(@dt, interval 1 minute); -加1分钟 date_add(@dt, interval 1 hour); -加1小时 date_add(@dt, interval 1 day); -加1天 date_add(@dt, interval 1 week); -加1周 date_add(@dt, interval 1 month); -加1月 date_add(@dt, interval 1 quarter); -加1季 date_add(@dt, interval 1 year); -加1年 为日期减去一个时间间隔:date_sub(),格式同date_add() 改写后:
> update test1 set CreateTime=date_add(CreateTime, interval 1 second),ModifyTime=date_add(ModifyTime, interval 1 second);
> select * from test1;
+-+-------------+-------------+
| Id | CreateTime | ModifyTime |
+-+-------------+-------------+
| 1 | 2017-08-01 18:31:00 | 2017-08-01 18:31:00 |
| 2 | 2017-08-01 18:31:02 | 2017-08-01 18:31:02 |
| 3 | 2017-08-01 18:31:03 | 2017-08-01 18:31:03 |
+-+-------------+-------------+
- SQL Server 存储过程
- ubuntu中配置hadoop
- jQuery选择器大全(48个代码片段+21幅图演示)
- C# 如何在Excel 动态生成PivotTable
- RabbitMQ入门HelloWorld(C#)(翻译)
- Centos环境下搭建Asp.NET Core环境和安装Jexus
- Linux系统Java环境安装配置
- ASP.NET Core 依赖注入
- 使用Hive SQL插入动态分区的Parquet表OOM异常分析
- 基于STS和JWT的微服务身份认证
- 小程序前端开发基础框架,可直接用于开发
- “盲”逆向:iOS 应用 Blind 寻踪
- Redis应用及安装
- 微服务实践分享与探讨
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解
- 谷歌开源NLP模型可视化工具LIT,模型训练不再「黑箱」
- Python 装饰器填坑指南 | 最常见的报错信息、原因和解决方案
- 社区开源框架预制件相关模块:CollectManager详解
- Kettle构建Hadoop ETL实践(三):Kettle对Hadoop的支持
- 3种 Springboot 全局时间格式化方式,别再写重复代码了
- 一文搞懂CDN加速原理
- 3分钟短文:Laravel Carbon自定义日期时间格式
- (30)字符截取命令sed
- 2. Bean Validation声明式校验方法的参数、返回值
- 如何识别和阻止基于电报的僵尸网络
- 由String,String Builder,String Buffer 引起的面试惨案
- MySQL案例:各类临时文件的存放位置
- 关于加@Transactional注解的方法之间调用,事务是否生效的问题
- 基于Vue实现一个有点意思的拼拼乐小游戏
- 硬核手写字节码实现HelloWorld