mysql no zero date_MySQL关于日期为零值的处理

2024-02-03 05:20

本文主要是介绍mysql no zero date_MySQL关于日期为零值的处理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:

前面文章我们介绍过日期和时间字段的查询方法,最近遇到日期值为零的问题。原来了解过和 sql_mode 参数设置有关,但还不是特别清楚,本篇文章将探究下MySQL怎么处理日期值为零的问题。

1.问题描述

这里我们说的日期为零值是指年、月、日为零,即'0000-00-00'。显然,这是不合法的日期值,但由于设计问题或历史遗留问题,有时候数据库中有类似日期值为零的数据,默认情况下插入零值日期会报错,可以通过修改参数sql_mode模式来避免该问题。下面展示下默认情况下插入零值的情况:

# 首先创建测试表

CREATE TABLE `t_zerodate` (

`increment_id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',

`year_col` year DEFAULT NULL COMMENT '年',

`date_col` date DEFAULT NULL COMMENT '日期',

`dt_col` datetime DEFAULT NULL COMMENT 'datetime时间',

`ts_col` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'timestamp时间',

PRIMARY KEY (`increment_id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='zerodate';

# 查看sql_mode模式

mysql> select @@sql_mode;

+----------------------------------------------------------------------------------------------------+

| @@sql_mode |

+----------------------------------------------------------------------------------------------------+

| STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |

+----------------------------------------------------------------------------------------------------+

# 分别插入年、月、日为零值测试

# 年份为0000 插入成功

mysql> insert into t_zerodate (year_col) values (0000);

Query OK, 1 row affected (0.02 sec)

# 月、日都不为零时 可插入成功

mysql> insert into t_zerodate (date_col) values ('0000-00-00');

ERROR 1292 (22007): Incorrect date value: '0000-00-00' for column 'date_col' at row 1

mysql> insert into t_zerodate (date_col) values ('0000-01-00');

ERROR 1292 (22007): Incorrect date value: '0000-01-00' for column 'date_col' at row 1

mysql> insert into t_zerodate (date_col) values ('0000-00-01');

ERROR 1292 (22007): Incorrect date value: '0000-00-01' for column 'date_col' at row 1

mysql> insert into t_zerodate (date_col) values ('0000-01-01');

Query OK, 1 row affected (0.02 sec)

2.sql_mode变更测试

关于sql_mode,原来写过一篇文章,sql_mode支持多个变量的不同组合,不同的sql_mode影响服务端支持的SQL语法以及数据校验规则。其中 NO_ZERO_IN_DATE、NO_ZERO_DATE这两个变量影响MySQL对日期零值的处理。上面测试中可以发现,严格模式下,当sql_mode中包含NO_ZERO_IN_DATE,NO_ZERO_DATE两个变量时,月和日都不为零时可以插入成功。

乍一看,NO_ZERO_IN_DATE和NO_ZERO_DATE两个变量很相似,但作用有什么不同呢?下面我们给出这两个变量的作用并做下具体测试。

NO_ZERO_DATE模式影响服务端是否允许将 '0000-00-00' 作为有效日期。其效果还取决于sql_mode是否启用了严格模式。

如果未启用此模式,'0000-00-00'则允许插入并且不会产生警告。

如果只启用此模式,'0000-00-00'则允许插入但是会产生警告。

如果启用了此模式和严格模式,'0000-00-00'则会被认定为非法,并且插入也会产生错误。除非同时带有IGNORE,对于 INSERT IGNORE和UPDATE IGNORE,'0000-00-00'则允许插入但是会产生警告。

NO_ZERO_IN_DATE模式影响服务端是否允许插入年份部分非零但月或日部分为0的日期。(例如'2010-00-01'或 '2010-01-00',但不影响日期'0000-00-00'),其效果同样还取决于sql_mode是否启用了严格模式。

如果未启用此模式,则允许部分为零的日期插入,并且不会产生任何警告。

如果只启用此模式,则将该零值日期插入为'0000-00-00'并产生警告。

如果启用了此模式和严格模式,则除非IGNORE同时指定,否则不允许插入为零的日期。对于INSERT IGNORE和 UPDATE IGNORE,将该零值日期插入为'0000-00-00'并产生警告。

同时,官方文档中指出:NO_ZERO_DATE和NO_ZERO_IN_DATE虽然不是严格模式的一部分,但应与严格模式结合使用,如果在未启用严格模式的情况下启用了NO_ZERO_DATE或NO_ZERO_IN_DATE则会产生警告,反之亦然,(sql_mode中包含STRICT_TRANS_TABLES,一般可认为启用了严格模式)。

下面我们来测试下,严格模式下分别启用和不启用这两个变量的效果:

1.严格模式下 同时启用NO_ZERO_DATE、NO_ZERO_IN_DATE

# 上文已经测试过,正常情况下 月、日都不为零时 可插入成功

# 下面测试insert ignore into

mysql> set session sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION";

Query OK, 0 rows affected (0.00 sec)

mysql> truncate table t_zerodate;

Query OK, 0 rows affected (0.07 sec)

mysql> insert ignore into t_zerodate (date_col) values ('0000-00-00');

Query OK, 1 row affected, 1 warning (0.01 sec)

mysql> insert ignore into t_zerodate (date_col) values ('2010-00-00');

Query OK, 1 row affected, 1 warning (0.01 sec)

mysql> insert ignore into t_zerodate (date_col) values ('2010-01-00');

Query OK, 1 row affected, 1 warning (0.01 sec)

mysql> insert ignore into t_zerodate (date_col) values ('2010-00-01');

Query OK, 1 row affected, 1 warning (0.01 sec)

mysql> select date_col from t_zerodate;

+------------+

| date_col |

+------------+

| 0000-00-00 |

| 0000-00-00 |

| 0000-00-00 |

| 0000-00-00 |

+------------+

# 结论:

正常情况下 月、日都不为零时 可插入成功;

对于INSERT IGNORE则允许插入,但会产生告警,并会将零值日期保存为'0000-00-00'。

2.严格模式下 不启用NO_ZERO_DATE

mysql> set session sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION";

Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> truncate table t_zerodate;

Query OK, 0 rows affected (0.08 sec)

mysql> insert into t_zerodate (date_col) values ('0000-00-00');

Query OK, 1 row affected (0.01 sec)

mysql> insert into t_zerodate (date_col) values ('2010-00-01');

ERROR 1292 (22007): Incorrect date value: '2010-00-01' for column 'date_col' at row 1

mysql> insert into t_zerodate (date_col) values ('2010-01-00');

ERROR 1292 (22007): Incorrect date value: '2010-01-00' for column 'date_col' at row 1

mysql> insert into t_zerodate (date_col) values ('0000-00-01');

ERROR 1292 (22007): Incorrect date value: '0000-00-01' for column 'date_col' at row 1

mysql> insert into t_zerodate (date_col) values ('0000-01-00');

ERROR 1292 (22007): Incorrect date value: '0000-01-00' for column 'date_col' at row 1

# 结论:

'0000-00-00'可以正常插入,其余月、日为零的日期插入会报错;

对于INSERT IGNORE则允许插入,但会产生告警,并会将零值日期保存为'0000-00-00'。

3.严格模式下 不启用NO_ZERO_IN_DATE

mysql> set session sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION";

Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> truncate table t_zerodate;

Query OK, 0 rows affected (0.07 sec)

mysql> insert into t_zerodate (date_col) values ('0000-00-00');

ERROR 1292 (22007): Incorrect date value: '0000-00-00' for column 'date_col' at row 1

mysql> insert into t_zerodate (date_col) values ('2010-00-00');

Query OK, 1 row affected (0.01 sec)

mysql> insert into t_zerodate (date_col) values ('2010-00-01');

Query OK, 1 row affected (0.00 sec)

mysql> insert into t_zerodate (date_col) values ('2010-01-00');

Query OK, 1 row affected (0.00 sec)

mysql> insert ignore into t_zerodate (date_col) values ('0000-00-00');

Query OK, 1 row affected, 1 warning (0.01 sec)

mysql> select date_col from t_zerodate;

+------------+

| date_col |

+------------+

| 2010-00-00 |

| 2010-00-01 |

| 2010-01-00 |

| 0000-00-00 |

+------------+

# 结论:

'0000-00-00'插入报错,其余月、日为零的日期可以正常插入;

对于INSERT IGNORE则允许插入'0000-00-00',但会产生告警。

4.严格模式下 NO_ZERO_DATE和NO_ZERO_IN_DATE都不启用

mysql> set session sql_mode = "STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION";

Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> truncate table t_zerodate;

Query OK, 0 rows affected (0.09 sec)

mysql> insert into t_zerodate (date_col) values ('0000-00-00');

Query OK, 1 row affected (0.01 sec)

mysql> insert into t_zerodate (date_col) values ('2010-00-00');

Query OK, 1 row affected (0.01 sec)

mysql> insert into t_zerodate (date_col) values ('2010-00-01');

Query OK, 1 row affected (0.01 sec)

mysql> insert into t_zerodate (date_col) values ('2010-01-00');

Query OK, 1 row affected (0.01 sec)

# 结论:

'0000-00-00'和其余月、日为零的日期都可以正常插入。

3.结论及建议

简单总结下,NO_ZERO_DATE模式影响'0000-00-00'日期的插入,NO_ZERO_IN_DATE模式影响除'0000-00-00'外的月、日为零的日期的插入。另外无论何种模式,YEAR类型都允许0000插入,这两个变量影响的是DATE、DATETIME、TIMESTAMP三种字段类型中对日期部分为零的处理。

至于我们是否要启用这两种模式,这取决于业务需求。如果你的业务有插入零值日期的需求,则可以选择sql_mode中不要包含NO_ZERO_DATE和NO_ZERO_IN_DATE,例如,某字段要求设置为DATE类型且不为空,默认值设为'0000-00-00'。一般情况下,NO_ZERO_DATE和NO_ZERO_IN_DATE建议同时有或者同时没有,有插入零日期值的需求则可以去除二者,没有此类需要则可以保留二者。这里提醒下,官方文档中讲到,这两个变量在未来版本中不再作为独立变量使用,故官方不推荐使用。

总结:

写了这么多,不知道你认真看了多少,其实本篇文章讲的东西还是比较简单的。如果你遇到过此类问题,再看下本篇文章可能理解会更深刻些,没遇过此类问题的小伙伴,希望这篇文章可以让你知道MySQL对于零值日期有不同的处理。

2f65deb287714bd3fd3c7157dfd951ef.png

这篇关于mysql no zero date_MySQL关于日期为零值的处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/673094

相关文章

Python调用LibreOffice处理自动化文档的完整指南

《Python调用LibreOffice处理自动化文档的完整指南》在数字化转型的浪潮中,文档处理自动化已成为提升效率的关键,LibreOffice作为开源办公软件的佼佼者,其命令行功能结合Python... 目录引言一、环境搭建:三步构建自动化基石1. 安装LibreOffice与python2. 验证安装

Python标准库datetime模块日期和时间数据类型解读

《Python标准库datetime模块日期和时间数据类型解读》文章介绍Python中datetime模块的date、time、datetime类,用于处理日期、时间及日期时间结合体,通过属性获取时间... 目录Datetime常用类日期date类型使用时间 time 类型使用日期和时间的结合体–日期时间(

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

MySQL中EXISTS与IN用法使用与对比分析

《MySQL中EXISTS与IN用法使用与对比分析》在MySQL中,EXISTS和IN都用于子查询中根据另一个查询的结果来过滤主查询的记录,本文将基于工作原理、效率和应用场景进行全面对比... 目录一、基本用法详解1. IN 运算符2. EXISTS 运算符二、EXISTS 与 IN 的选择策略三、性能对比

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

SQL Server跟踪自动统计信息更新实战指南

《SQLServer跟踪自动统计信息更新实战指南》本文详解SQLServer自动统计信息更新的跟踪方法,推荐使用扩展事件实时捕获更新操作及详细信息,同时结合系统视图快速检查统计信息状态,重点强调修... 目录SQL Server 如何跟踪自动统计信息更新:深入解析与实战指南 核心跟踪方法1️⃣ 利用系统目录

MySQL 内存使用率常用分析语句

《MySQL内存使用率常用分析语句》用户整理了MySQL内存占用过高的分析方法,涵盖操作系统层确认及数据库层bufferpool、内存模块差值、线程状态、performance_schema性能数据... 目录一、 OS层二、 DB层1. 全局情况2. 内存占js用详情最近连续遇到mysql内存占用过高导致

Python进行JSON和Excel文件转换处理指南

《Python进行JSON和Excel文件转换处理指南》在数据交换与系统集成中,JSON与Excel是两种极为常见的数据格式,本文将介绍如何使用Python实现将JSON转换为格式化的Excel文件,... 目录将 jsON 导入为格式化 Excel将 Excel 导出为结构化 JSON处理嵌套 JSON:

Mysql中设计数据表的过程解析

《Mysql中设计数据表的过程解析》数据库约束通过NOTNULL、UNIQUE、DEFAULT、主键和外键等规则保障数据完整性,自动校验数据,减少人工错误,提升数据一致性和业务逻辑严谨性,本文介绍My... 目录1.引言2.NOT NULL——制定某列不可以存储NULL值2.UNIQUE——保证某一列的每一

解密SQL查询语句执行的过程

《解密SQL查询语句执行的过程》文章讲解了SQL语句的执行流程,涵盖解析、优化、执行三个核心阶段,并介绍执行计划查看方法EXPLAIN,同时提出性能优化技巧如合理使用索引、避免SELECT*、JOIN... 目录1. SQL语句的基本结构2. SQL语句的执行过程3. SQL语句的执行计划4. 常见的性能优