mysql5.7 TIMESTAMP NOT NULL DEFAULT ‘0000-00-00 00:00:00‘ 换版8版本 引发的问题

devtools/2024/10/22 18:31:20/

mysql5.7 TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' 换版引发的问题

  • 问题背景
  • sql_mode
  • 上机演示
    • 5.7
    • 8.4

问题背景

在项目mysql版本由5.7 换版到8.4版本后,我们进行回归测试时,却发现一个积年代码报错了,是数据库插入报的错 xxx can not be null,!!!∑(゚Д゚ノ)ノ
这都是多早的老代码了,怎么会报这个错!人直接傻了。查看代码,那个字段确实没有设置任何值,然后查看数据库表结构,发现那个字段定义有点奇怪,upTime TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '更新时间',默认值是 0000-00-00 00:00:00,而不是常见的CURRENT_TIMESTAMP。但似乎也啥关联,要命的是字段明明是非空,为什么在5.7版本会插入成功!??

sql_mode

sql_mode 是 MySQL 中的一个系统变量,用于控制 MySQL 服务器运行时的 SQL 模式,影响 MySQL 的行为和功能。SQL 模式定义了 MySQL 服务器应该执行 SQL 语句的方式,包括语法检查、数据验证、警告和错误处理等方面。

在 MySQL 中,sql_mode 可以通过多种方式设置,包括在配置文件中指定默认的 sql_mode,在会话级别或全局级别动态修改 sql_mode。以下是一些常见的 sql_mode 设置:

  1. STRICT_TRANS_TABLES:在这种模式下,MySQL 会对插入、更新和删除操作进行严格的数据类型检查,确保数据的完整性。如果数据类型不匹配或值超出范围,将会产生错误。
  2. NO_ZERO_DATE:禁止插入 ‘0000-00-00’ 或 ‘0000-00-00 00:00:00’ 作为日期或日期时间值, 如果发现这样的值,会产生错误。
  3. ONLY_FULL_GROUP_BY:在这种模式下,如果在 GROUP BY 子句中的列没有在 SELECT 列表中出现,将会产生错误,要求所有非聚合列都出现在 GROUP BY 子句中。
  4. ERROR_FOR_DIVISION_BY_ZERO:在除法运算中如果除数为 0,会产生错误,而不是返回 NULL。
  5. ANSI_QUOTES:启用 ANSI_QUOTES 模式后,双引号被视为引用标识符的引号,而不是字符串引号。
  6. NO_ZERO_IN_DATE:设置该值,mysql数据库在严格模式下,不允许日期和月份为零

通过设置合适的 sql_mode,您可以控制 MySQL 的行为,使其符合您的需求和标准。根据项目的要求,可以选择不同的模式来确保数据的正确性和一致性。

那么,我们查看mysql5.7的官方文档,发现,mysql5.7 里面的 默认 sql_mode模式,里面有NO_ZERO_DATENO_ZERO_IN_DATE
在这里插入图片描述
所以,其实在5.7 版本默认配置中,这样的建表语句是非法的。那么我们找一个环境试一试!我用的是一个在线网站,小闪电

上机演示

5.7

mysql> select version();
+-------------------------+
| version()               |
+-------------------------+
| 5.7.42-0ubuntu0.18.04.1 |
+-------------------------+
1 row in set (0.00 sec)mysql> SELECT @@sql_mode;
+-------------------------------------------------------------------------------------------------------------------------------------------+
| @@sql_mode                                                                                                                                |
+-------------------------------------------------------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+-------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)mysql> create database te-> ;
Query OK, 1 row affected (0.00 sec)mysql> use te;
Database changedmysql>  CREATE TABLE stu (->   id INT,->   upTime TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '更新时间',->   st CHAR(2) NOT NULL DEFAULT '0' COMMENT '状态'-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='学生表';
ERROR 1067 (42000): Unknown error 1067

果然出错了,于是我们修改一下,sql_mode ,在试一遍

mysql> SET  sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
Query OK, 0 rows affected, 2 warnings (0.00 sec)mysql>  CREATE TABLE stu (->   id INT,->   upTime TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '更新时间',->   st CHAR(2) NOT NULL DEFAULT '0' COMMENT '状态'-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='学生表';
Query OK, 0 rows affected (0.34 sec)mysql> insert into stu(id,upTime,st) values (1,null,null);
ERROR 1048 (23000): Unknown error 1048
mysql> insert into stu(id,upTime,st) values (1,null,'1');
Query OK, 1 row affected (0.06 sec)mysql> insert into stu(id,upTime,st) values (2,null,null);
ERROR 1048 (23000): Unknown error 1048
mysql> select * from stu;
+------+---------------------+----+
| id   | upTime              | st |
+------+---------------------+----+
|    1 | 2024-09-02 09:37:07 | 1  |
+------+---------------------+----+
1 row in set (0.00 sec)

我们可以看到插入成功了,而且,upTime 的值 竟然是当前时间!而且,当我同时令st也为null 时,插入报错了!于我最初设想的结果有些出入,看来是只有 TIMESTAMP 这个类型,mysql5.7 做了特殊的处理,其他类型设置为非空时,即使有默认值也不能直接插入null。

8.4

然而,mysql8.4 的版本中,即使你重新修改了 sql_mode的值,允许0日期。但是也不能直接插入null给一个表结构为非空的日期字段。感兴趣的同学可以试一试。这边没什么好贴图的,直接就报了xx can not be null


http://www.ppmy.cn/devtools/105213.html

相关文章

【舍入,取整,取小数,取余数丨Excel 函数】

数学函数 1、Round函数 Roundup函数 Rounddown函数 取整:(Int /Trunc)其他舍入函数: 2、Mod函数用Mod函数提取小数用Mod函数 分奇偶通过身份证号码判断性别 1、Round函数 Roundup函数 Rounddown函数 Round(数字,保留几位小数)(四…

JavaEE 第21节 UDP数据报结构剖析

目录 前言报文结构1、源端口号&目的端口号2、UDP长度3、校验和概念校验和计算方法 前言 本篇文章会围绕UDP报文的结构,对此协议展开详细的讲解,比如报文中每个字段的作用、以及填写方式。 阅读完这篇文章,你会对UDP数据报结构有个透彻的…

[BJDCTF 2020]easy_md5

打开题目所在的环境可以看到一个平平无奇的提交框,在尝试提交的时候抓包发现给了提示: 在 Response 包中的 Header 中存在 Hint 为: hint: select * from admin where passwordmd5($pass,true) 在这里我们尝试MD5 绕过,只需要传入…

20240902软考架构-------软考96-100答案解析

每日打卡题96-100答案 96、【2018年真题】 难度:难 CORBA服务端构件模型中, 是CORBA对象的真正实现,负责完成客户端请求。 A.伺服对象(Servant) B.对象适配器(Object Adapter) C.对象请求代理&…

C高级编程 第十三天(链表的初始化 插入 遍历 清除 销毁)

目录 1.链表结构体 2.初始化链表 3.插入节点 4.遍历链表 5.删除链表 5.1按位置删除 5.2按值删除 6.清空链表 7.销毁链表 1.链表结构体 struct LinkNode {void* data; //数据域struct LinkNode* next; //指针域 };struct LList {struct LinkNode pHeader; //…

leetcode67二进制

补充知识 python中二进制由前缀0b表示位运算 & &#xff08;按位与&#xff09;| &#xff08;按位或&#xff09;^ &#xff08;按位异或&#xff09;~ &#xff08;按位取反&#xff09;<< &#xff08;左移&#xff09;>> &#xff08;右移&#xff09; 格…

前后端分离项目遇到的跨域问题解决方案(后端为主)

文章目录 什么是跨域问题&#xff1f;第一种方式 ⇒ 注解解决方案&#xff1a;第二种方式 ⇒ 使用 CorsFilter 方法解决&#xff1a;第三种方式 ⇒ 实现 WebMvcConfigure 接口&#xff0c;添加映射&#xff08;个人推荐&#xff09; 什么是跨域问题&#xff1f; 先说问题&#…

Anndata: AttributeError: ‘DataFrame’ object has no attribute ‘dtype’

Anndata: AttributeError: ‘DataFrame’ object has no attribute ‘dtype’ 背景解决方法 背景 在使用anndata做切片时&#xff0c;比如下面这样的例子 sub_rna rna[:10] # rna is anndata出现如下报错&#xff1a; AttributeError: ‘DataFrame’ object has no attribu…