GreatSQL5.7 与 8.0 对 DATE 非法值处理方式不同

news/2025/3/9 10:19:42/文章来源:https://www.cnblogs.com/greatsql/p/18757160

GreatSQL5.7 与 8.0 对 DATE 非法值处理方式不同

一、问题描述

1. 问题现象

当分别通过LOAD DATA LOCAL INFILEINSERT导入非法的 DATE 字段数据时,在5.7.21和 8.0.25使用LOAD DATA LOCAL会报一个Warning,数据异常但可以插入成功,而且实际插入的数据跟用户计划插入的不同,具体是0000-00-00;而使用LOAD DATA INFILE方式导入和INSERT非法值则直接报错,表里不会插入数据。

二、问题分析

1、LOAD DATA INFILE的使用模式

有普通模式和 LOCAL 模式。普通模式要求数据文件放在数据库服务器上,基于行内数据库容器化的情况,目前统一使用 LOCAL 模式。

2、LOAD DATA LOCAL INFILE方式导入的处理机制

LOAD DATA LOCAL INFILE的特殊处理机制,相当于自动置上IGNORE,官方文档有明确说明。

LOCAL also affects error handling.
With LOAD DATA INFILE,Data interpretation  and duplicate-key errors terminate the operation.
With LOAD DATA LOCAL INFILE,Data interpretation errors and duplicate-key errors become warnings and the operation continues because the server has no way to stop transmission in the middle of the operation. For duplicate-key errors, this is same as if IGNORE is specified. IGNORE is explained further later in this section.

而在源码LOCAL INFILE里加上IGNORE标识的代码:

          opt_duplicate INTO TABLE_SYM table_ident opt_use_partition{LEX *lex=Lex;/* Fix lock for LOAD DATA CONCURRENT REPLACE */if (lex->duplicates == DUP_REPLACE && $4 == TL_WRITE_CONCURRENT_INSERT)$4= TL_WRITE_DEFAULT;if (!Select->add_table_to_list(YYTHD, $12, NULL, TL_OPTION_UPDATING,$4, $4 == TL_WRITE_LOW_PRIORITY ?MDL_SHARED_WRITE_LOW_PRIO :MDL_SHARED_WRITE, NULL, $13))MYSQL_YYABORT;lex->load_field_list.empty();lex->load_update_list.empty();lex->load_value_list.empty();/* We can't give an error in the middle when using LOCAL files */if (lex->local_file && lex->duplicates == DUP_ERROR)lex->set_ignore(true);}/* We can't give an error in the middle when using LOCAL files */if (m_cmd.m_is_local_file && lex->duplicates == DUP_ERROR)lex->set_ignore(true);

因此,上述代码里针对LOAD DATA LOACL INFILE加 IGNORE 属于数据库的正常行为,

但官方文档未给出对 LOCAL 加上IGNORE未有进一步的说明,只是描述了IGNORE对语句执行的影响。

IGNORE关键字和严格 SQL 模式同时生效时,IGNORE关键字优先。

The following table presents a summary comparison of statement behavior when the default is to produce an error versus a warning. An example of when the default is to produce an error is inserting a NULL into a NOT NULL column. An example of when the default is to produce a warning is inserting a value of the wrong data type into a column (such as inserting the string 'abc' into an integer column).
Operational Mode When Statement Default is Error When Statement Default is Warning
Without IGNORE or strict SQL mode Error Warning
With IGNORE Warning Warning (same as without IGNORE or strict SQL mode)
With strict SQL mode Error (same as without IGNORE or strict SQL mode) Error
With IGNORE and strict SQL mode Warning Warning
One conclusion to draw from the table is that when the IGNORE keyword and strict SQL mode are both in effect, IGNORE takes precedence. This means that, although IGNORE and strict SQL mode can be considered to have opposite effects on error handling, they do not cancel when used together.

在严格模式下是不允许使用零部分的日期,并且插入会产生错误,除非使用IGNORE,会将将零部分的日期插入为 '0000-00-00'(这在数据库中被视为有效IGNORE)并产生警告。

lf strict mode is enabled, dates with zero parts are not permitted and inserts produce an error, unless IGNORE is given as WelL. For INSERT IGNORE and UPDATE IGNORE, dates with zero parts are inserted as '0000-00-00' (which is consideredvalid with IGNORE) and produce a warning.

3、问题重现

3.1 基线设置

5.7.21和8.0.25的SQL_MODE:

greatsql>SHOW GLOBAL VARIABLES LIKE 'SQL_MODE';
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value                                                                                                                                     |
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| 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 |
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+

3.2 测试情况

LOAD DATA INFILE测试情况

在存在非法数值的情况下,导入命令报错"ERROR 1292 (22007): Incorrect date value: '0000-00-00' for column 'c_date' at row 1"。

greatsql> TRUNCATE TABLE testdb.t2;
Query OK, 0 rows affected (0.04 sec)greatsql> LOAD DATA INFILE '/data/greate/t1_00.csv' INTO TABLE testdb.t2 FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY "\r\n";
ERROR 1292 (22007): Incorrect date value: '0000-00-00' for column 'c_date' at row 1
greatsql>
LOAD DATA LOCAL INFILE测试情况

在存在非法数值的情况下,导入命令不报错,但是会输出"warning:Data truncated for column 'a' at row 1",表明GreatSQL识别到了非法字符串,并将其自动进行TRUNCATE转换成了数据类型的默认值。

$ echo 0002024-06 > test.txtgreatsql> CREATE TABLE t1 ( a date primary key);
Query OK, 0 rows affected (0.15 sec)greatsql> LOAD DATA LOCAL INFILE '/root/test.txt' INTO TABLE t1;
Query OK, 1 row affected, 1 warning (0.00 sec)
Records: 1  Deleted: 0  Skipped: 0  Warnings: 1greatsql> SHOW WARNINGS;
+---------+------+----------------------------------------+
| Level   | Code | Message                                |
+---------+------+----------------------------------------+
| Warning | 1265 | Data truncated for column 'a' at row 1 |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)greatsql> SELECT * FROM t1;
+------------+
| a          |
+------------+
| 0000-00-00 |
+------------+
1 row in set (0.00 sec)
INSERT 测试情况

在存在非法数值的情况下,执行INSERT命令报错"ERROR 1292 (22007): Incorrect date value: '0000-00-00' for column 'c_date' at row 1"。

greatsql> SHOW CREAET TABLE  t2\G
*************************** 1. row ***************************Table: t2
Create Table: CREATE TABLE `t2` (`c1` int NOT NULL,`c2` int DEFAULT NULL,`c_date` date DEFAULT '2000-01-01',`c_ts` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,`c_dt` datetime DEFAULT '2000-01-01 00:00:00'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
1 row in set (0.00 sec)greatsql> INSERT INTO  testdb.t2 VALUES (1,1,"0000-00-00",now(),"2000-01-01 00:00:00");
ERROR 1292 (22007): Incorrect date value: '0000-00-00' for column 'c_date' at row 1
greatsql> 
INSERT + IGNORE 测试情况

在存在非法数值的情况下,导入命令不报错,但是会输出"Warning:Out of range value for column 'c_date' at row 1",表明GreatSQL识别到了非法字符串,并也自动进行TRUNCATE转换成数据类型的默认值。

greatsql> INSERT IGNORE INTO testdb.t2 VALUES (1,1,"0000-00-00",now(),"2000-01-01 00:00:00");
Query OK, 1 row affected, 1 warning (0.01 sec)greatsql> SHOW WARNINGS;
+---------+------+-------------------------------------------------+
| Level   | Code | Message                                         |
+---------+------+-------------------------------------------------+
| Warning | 1264 | Out of range value for column 'c_date' at row 1 |
+---------+------+-------------------------------------------------+
1 row in set (0.00 sec)greatsql> INSERT IGNORE INTO  testdb.t2 VALUES (1,1,"002000-00-00",now(),"2000-01-01 00:00:00");
Query OK, 1 row affected, 1 warning (0.01 sec)greatsql> SELECT * FROM testdb.t2;
+----+------+------------+---------------------+---------------------+
| c1 | c2   | c_date     | c_ts                | c_dt                |
+----+------+------------+---------------------+---------------------+
|  1 |    1 | 0000-00-00 | 2024-06-05 13:57:29 | 2000-01-01 00:00:00 |
|  1 |    1 | 0000-00-00 | 2024-06-05 13:59:55 | 2000-01-01 00:00:00 |
+----+------+------------+---------------------+---------------------+
2 rows in set (0.00 sec)
其它日期类型存在类似的ERROR和WARNING

除了"date"类型,其他时间类型存在同样的问题,例如"datetimetimestamp"等。

greatsql> CREATE TABLE t3 ( a datetime );
greatsql> LOAD DATA LOCAL INFILE '/home/greatdb/test.txt' INTO TABLE t3;
Query OK, 1 row affected, 1 warning (0.01 sec)
Records: 1  Deleted: 0  Skipped: 0  Warnings: 1
greatsql> SHOW WARNINGS;
+---------+------+----------------------------------------+
| Level   | Code | Message                                |
+---------+------+----------------------------------------+
| Warning | 1265 | Data truncated for column 'a' at row 1 |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)
greatsql> SELECT * FROM t3;
+---------------------+
| a                   |
+---------------------+
| 0000-00-00 00:00:00 |
+---------------------+
1 row in set (0.00 sec)
greatsql> CREATE TABLE  t4 ( a timestamp);
greatsql> LOAD DATA LOCAL INFILE '/home/greate/test.txt' INTO TABLE t4;
Query OK, 1 row affected, 1 warning (0.01 sec)
Records: 1  Deleted: 0  Skipped: 0  Warnings: 1greatsql> SHOW WARNINGS;
+---------+------+----------------------------------------+
| Level   | Code | Message                                |
+---------+------+----------------------------------------+
| Warning | 1265 | Data truncated for column 'a' at row 1 |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)greatsql> SELECT * FROM t4;
+---------------------+
| a                   |
+---------------------+
| 0000-00-00 00:00:00 |
+---------------------+
1 row in set (0.00 sec)
默认值测试

当数据存在问题时,无论是LOAD DATA还是INSERT,GreatSQL内部都会自动进行TRUNCATE转换成数据类型的默认值。只有当字段缺省时,才会使用表中字段的default缺省值。

greatsql> LOAD DATA LOCAL INFILE '/tmp/t1.csv' INTO TABLE TESTDB.T2 FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY "\r\n";
Query OK, 1 rows affected, 1 warning (0.01 sec)
Records: 1  Deleted: 0  Skipped: 0  Warnings: 1greatsql> INSERT IGNORE INTO testdb.t2 VALUES (1,1,"002000-00-00",now(),"2000-01-01 00:00:00");
Query OK, 1 row affected, 1 warning (0.01 sec)greatsql> SHOW WARNINGS;
+---------+------+-------------------------------------------------+
| Level   | Code | Message                                         |
+---------+------+-------------------------------------------------+
| Warning | 1264 | Out of range value for column 'c_date' at row 1 |
+---------+------+-------------------------------------------------+
1 row in set (0.00 sec)greatsql> INSERT IGNORE INTO testdb.t2 VALUES (3,3,NULL,now(),"2000-01-01 00:00:00");
Query OK, 1 row affected (0.01 sec)greatsql> INSERT IGNORE INTO testdb.t2 VALUES (4,4,"",now(),"2000-01-01 00:00:00");
Query OK, 1 row affected, 1 warning (0.01 sec)greatsql> SHOW WARNINGS;
+---------+------+---------------------------------------------+
| Level   | Code | Message                                     |
+---------+------+---------------------------------------------+
| Warning | 1265 | Data truncated for column 'c_date' at row 1 |
+---------+------+---------------------------------------------+
1 row in set (0.00 sec)greatsql> INSERT INTO testdb.t2(c1,c2) VALUES (5,5);
Query OK, 1 row affected (0.01 sec)greatsql> SELECT * FROM  testdb.t2;
+----+------+------------+---------------------+---------------------+
| c1 | c2   | c_date     | c_ts                | c_dt                |
+----+------+------------+---------------------+---------------------+
|  1 |    1 | 0000-00-00 | 2024-06-05 13:57:29 | 2000-01-01 00:00:00 |
|  1 |    1 | 0000-00-00 | 2024-06-05 13:59:55 | 2000-01-01 00:00:00 |
|  3 |    3 | NULL       | 2024-06-05 14:03:40 | 2000-01-01 00:00:00 |
|  4 |    4 | 0000-00-00 | 2024-06-05 14:04:07 | 2000-01-01 00:00:00 |
|  5 |    5 | 2000-01-01 | 2024-06-05 14:11:48 | 2000-01-01 00:00:00 |
+----+------+------------+---------------------+---------------------+
5 rows in set (0.00 sec)
主键冲突场景测试

主键冲突场景下的ERROR,也会被LOAD DATA LOCAL INFILE当作WARNING处理,该行不进行插入。

greatsql> LOAD DATA LOCAL INFILE '/tmp/t1.csv' INTO TABLE testdb.t2 FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY "\r\n";
Query OK, 1 row affected, 2 warnings (0.01 sec)
Records: 2  Deleted: 0  Skipped: 1  Warnings: 2greatsql> SHOW WARNINGS;
+---------+------+---------------------------------------------+
| Level   | Code | Message                                     |
+---------+------+---------------------------------------------+
| Warning | 1265 | Data truncated for column 'c_date' at row 2 |
| Warning | 1062 | Duplicate entry '1' for key 't2.PRIMARY'    |
+---------+------+---------------------------------------------+
2 rows in set (0.00 sec)greatsql> SELECT * FROM t2;
+----+------+--------+---------------------+------+
| c1 | c2   | c_date | c_ts                | c_dt |
+----+------+--------+---------------------+------+
|  1 |    1 | NULL   | 2024-06-05 09:26:58 | NULL |
+----+------+--------+---------------------+------+
1 row in set (0.00 sec)greatsql> SYSTEM CAT /tmp/t1.csv
1,1,\N,"2024-06-05 09:26:58",\N
1,2,null,"2024-06-05 09:26:58",\Ngreatsql> SHOW CREATE TABLE t2\G
*************************** 1. row ***************************Table: t2
Create Table: CREATE TABLE `t2` (`c1` int NOT NULL,`c2` int DEFAULT NULL,`c_date` date DEFAULT '2000-01-01',`c_ts` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,`c_dt` datetime DEFAULT '2000-01-01 00:00:00',PRIMARY KEY (`c1`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
1 row in set (0.00 sec)

三、问题总结

1、 问题原因

特性如此,属于正常情况。

2、 解决方案建议

1、数据预处理

在导入数据前,使用脚本或程序对数据进行预处理,确保所有日期值都是合法的。例如,可以使用正则表达式或日期解析库来验证和格式化日期。

2、导入验证

将含有日期非法值的数据文件通过导入程序的LOAD DATA LOCAL INFILE方式导入时,会产生 Warning | 1265 | Data truncated for column 'a' at row 1。建议导入程序可以在导入后通过SHOW WARINGS语句检查下导入过程,如果出现类似warning,则说明存在非法数据转换。

注意LOAD DATA LOCAL INFILE无法指定数据异常时的处理机制,也无法通过设置字段默认值来指定,由数据库内部统一按照数据类型的默认值处理。

3、建议应用使用数据库以外的工具进行数据导入。

4、修改sql_mode,添加ALLOW_INVALID_DATES,允许不合法的 date 数据导入。


Enjoy GreatSQL 😃

关于 GreatSQL

GreatSQL是适用于金融级应用的国内自主开源数据库,具备高性能、高可靠、高易用性、高安全等多个核心特性,可以作为MySQL或Percona Server的可选替换,用于线上生产环境,且完全免费并兼容MySQL或Percona Server。

相关链接: GreatSQL社区 Gitee GitHub Bilibili

GreatSQL社区:

社区博客有奖征稿详情:https://greatsql.cn/thread-100-1-1.html

image-20230105161905827

技术交流群:

微信:扫码添加GreatSQL社区助手微信好友,发送验证信息加群

image-20221030163217640

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/894979.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hyper-V的安装过程自动化程度较高,但要了解每个安装步骤背后的原理

Hyper-V的安装过程确实具有较高的自动化程度,但了解每个安装步骤背后的原理对于确保安装的成功以及后续的维护和管理至关重要。以下是对Hyper-V安装过程中每个关键步骤及其原理的详细解析:一、准备工作 步骤:检查系统要求、备份数据、关闭不必要的程序。 原理: 系统要求:确…

牛客题解 | 拼凑三角形

牛客题库题解题目 题目链接 题解 题目难度:简单 知识点:数学逻辑 思路: 三角形成立的条件:1.为了更简便的判断三角形是否成立,将三个数由小到大进行排序放入a[3]中,只需要满足a[0]+a[1]>a[2]即可。(两个较小的数相加大于第三个数)。 2.若a[0]+a[1]&…

内网环境部署Deepseek+Dify,构建企业私有化AI应用

0.简介 公司为生产安全和保密,内部的服务器不可连接外部网络,为了可以在内网环境下部署,采用的方案为ollama(Docker)+Dify(Docker Compose),方便内网环境下迁移和备份,下文将介绍部署的全部过程。 1.镜像拉取 镜像拉取为准备工作,因服务器在内网环境,需要先在可以连接外…

牛客题解 | 拍照队形

牛客题库题解题目 题目链接 题解 题目难度:简单难度 知识点:数学逻辑 分析:主要考虑输出格式,由于N=3k+1,那么前K行每行输出2个字符,后k+1行输出1个字符。对于前k行,第一行:第一列输出字符,空格数为m=2*k-1,在输出第二个字符;第二行:先空格1,输出字符,空格m-=2个(…

电动后尾门控制器PLGM

经纬恒润平台化的电动尾门控制器PLGM可为不同的后尾门应用场合提供解决方案,目前已为众多客户配套量产。 经纬恒润平台化的电动尾门控制器PLGM(Power Lift Gate Module,PLGM)可为不同的后尾门应用场合提供解决方案,目前已为众多客户配套量产。主要功能车门电动打开…

CentOS 磁盘扩容lvm(虚拟机环境)

fdisk -l 查看磁盘情况对新增加的硬盘进行分区,使用fdisk命令创建和维护分区表。 fdisk /dev/vda 输入p:查看已分区数量(有两个 /dev/vda1 /dev/vda2) 输入n(new partition):新增加一个分区 输入p(parimary partition):分区类型选择为主分区 输入分区号3(partition …

Vue 自定义指令封装实现防抖 防止按钮暴力点击

本来项目前期没有做按钮防抖功能 快结束时才想起来 然后一个个写太慢了 然后就想着封装一下 vue3:新建directive.jsexport default {//自定义节流操作preventReClick: {mounted(el, binding) {el.addEventListener(click, () => {if (!el.disabled) {el.disabled = truesetT…

3.6 CW 模拟赛 T3. 列表

思路题意 有一个长度为 2n+12 \times n + 12n+1 的整数列表 aaa 初始恰好为 1∼2n+11 \sim 2 \times n + 11∼2n+1 的排列; 有一个集合 S\mathbb{S}S 初始为空, 进行 n+1n + 1n+1 次操作, 第 iii 次操作如下:111. 选择列表最中间位置的数第 n+2−in + 2 - in+2−i 个数, 从列表…

Navicat 操作 MySql 修改表结构时保存后直接卡死无反应问题

一、问题如下:在Navicat中调整表结构,添加新的字段。之后保存的时候就一直显示正在保存,等了一会儿也一直没有反应,点关闭也停止不了保存操作,就一直卡着。二、问题解决1、查看当前的进程列表: show processlist会发现有等待的进程:这些进程状态为Waiting for table met…

SAP 3M胶带:行业解决方案的革新者

SAP 3M胶带:行业解决方案的革新者 在胶带加工行业,SAP 3M胶带凭借其卓越的性能和广泛的应用领域,成为了众多企业的首选。而SAP与3M的结合,更是将科技与创新完美融合,为行业带来了全新的解决方案。库存管理痛点解决 胶带加工行业的多变性使得库存管理成为了一大痛点。然而,…

OPC DA获取DCS数据(配置DCOM)

OPC DA配置操作手册配置完成后,访问远程ip,就能获取到服务 C#使用Interop.OPCAutomation采集OPC DA数据,支持订阅(数据变化)、单个读取、单个写入、断线重连 qq:505645074

Hyper-V虚拟机黑屏还可能与虚拟机的显示配置有关,需要检查哪些?

Hyper-V虚拟机黑屏确实可能与虚拟机的显示配置有关。在处理这类问题时,需要检查以下几个方面:一、图形处理器设置 检查虚拟化模式: 进入虚拟机的设置,找到“显示”或“图形处理器”选项。 确认是否选择了正确的图形处理器虚拟化模式。例如,有时选择集成显卡模式可能导致黑…