百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

'0000-00-00'日期可以存入MySQL吗

ztj100 2025-03-28 23:30 10 浏览 0 评论

前言:

前面文章我们介绍过日期和时间字段的查询方法,最近遇到日期值为零的问题。原来了解过和 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对于零值日期有不同的处理。

相关推荐

使用 Pinia ORM 管理 Vue 中的状态

转载说明:原创不易,未经授权,谢绝任何形式的转载状态管理是构建任何Web应用程序的重要组成部分。虽然Vue提供了管理简单状态的技术,但随着应用程序复杂性的增加,处理状态可能变得更具挑战性。这就是为什么...

Vue3开发企业级音乐Web App 明星讲师带你学习大厂高质量代码

Vue3开发企业级音乐WebApp明星讲师带你学习大厂高质量代码下栽课》jzit.top/392/...

一篇文章说清 webpack、vite、vue-cli、create-vue 的区别

webpack、vite、vue-cli、create-vue这些都是什么?看着有点晕,不要怕,我们一起来分辨一下。...

超赞 vue2/3 可视化打印设计VuePluginPrint

今天来给大家推荐一款非常不错的Vue可拖拽打印设计器Hiprint。引入使用//main.js中引入安装import{hiPrintPlugin}from'vue-plugin-...

搭建Trae+Vue3的AI开发环境(vue3 ts开发)

从2024年2025年,不断的有各种AI工具会在自媒体中火起来,号称各种效率王炸,而在AI是否会替代打工人的话题中,程序员又首当其冲。...

如何在现有的Vue项目中嵌入 Blazor项目?

...

Vue中mixin怎么理解?(vue的mixins有什么用)

作者:qdmryt转发链接:https://mp.weixin.qq.com/s/JHF3oIGSTnRegpvE6GSZhg前言...

Vue脚手架安装,初始化项目,打包并用Tomcat和Nginx部署

1.创建Vue脚手架#1.在本地文件目录创建my-first-vue文件夹,安装vue-cli脚手架:npminstall-gvue-cli安装过程如下图所示:创建my-first-vue...

新手如何搭建个人网站(小白如何搭建个人网站)

ElementUl是饿了么前端团队推出的桌面端UI框架,具有是简洁、直观、强悍和低学习成本等优势,非常适合初学者使用。因此,本次项目使用ElementUI框架来完成个人博客的主体开发,欢迎大家讨论...

零基础入门vue开发(vue快速入门与实战开发)

上面一节我们已经成功的安装了nodejs,并且配置了npm的全局环境变量,那么这一节我们就来正式的安装vue-cli,然后在webstorm开发者工具里运行我们的vue项目。这一节有两种创建vue项目...

.net core集成vue(.net core集成vue3)

react、angular、vue你更熟悉哪个?下边这个是vue的。要求需要你的计算机安装有o.netcore2.0以上版本onode、webpack、vue-cli、vue(npm...

使用 Vue 脚手架,为什么要学 webpack?(一)

先问大家一个很简单的问题:vueinitwebpackprjectName与vuecreateprojectName有什么区别呢?它们是Vue-cli2和Vue-cli3创建...

vue 构建和部署(vue项目部署服务器)

普通的搭建方式(安装指令)安装Node.js检查node是否已安装,终端输入node-v会使用命令行(安装)npminstallvue-cli-首先安装vue-clivueinitwe...

Vue.js 环境配置(vue的环境搭建)

说明:node.js和vue.js的关系:Node.js是一个基于ChromeV8引擎的JavaScript运行时环境;类比:Java的jvm(虚拟机)...

vue项目完整搭建步骤(vuecli项目搭建)

简介为了让一些不太清楚搭建前端项目的小白,更快上手。今天我将一步一步带领你们进行前端项目的搭建。前端开发中需要用到框架,那vue作为三大框架主流之一,在工作中很常用。所以就以vue为例。...

取消回复欢迎 发表评论: