MySQL INSERT INTO SELECT 不匹配的记录由函数 str_to_date 触发
MySQL INSERT INTO SELECT not matching records are triggered by function str_to_date
我有一个奇怪的 MySQL INSERT SELECT 行为,我需要将 dt_int 从 TABLE2 转换为 TABLE1 中的日期时间 dt。
table 结构是
TABLE1
PK INT(11) -- auto increment
dt datetime
TABLE2
PK INT(11) -- auto increment
dt_int INT(11)
我有这样的插入 select 查询
INSERT INTO TABLE1(dt)
(
SELECT str_to_date(dt_int, '%Y%m%d')
FROM TABLE2
WHERE str_to_date(dt_int, '%Y%m%d') IS NOT NULL
)
如果 table 中的所有日期都有效,则可以正常工作。但是,如果 table 包含类似这样的数据
TABLE2
PK | dt_int
1 20201209
2 20202020
它会遇到错误代码 1411:函数 str_to_date.
的日期时间值“20202020”不正确
内部select 语句returns 仅有效日期,但插入语句仍尝试转换那些被过滤的日期。为什么会这样?有什么我可以做的吗?
[已编辑]
MySQL版本是5.7,引擎是InnoDB。当前托管在 Windows 环境中。
INSERT INTO table1
SELECT PK, CONCAT(dt_int DIV 10000, '-1-1')
+ INTERVAL dt_int MOD 10000 DIV 100 - 1 MONTH
+ INTERVAL dt_int MOD 100 - 1 DAY
FROM table2
WHERE 0 + DATE_FORMAT(CONCAT(dt_int DIV 10000, '-1-1')
+ INTERVAL dt_int MOD 10000 DIV 100 - 1 MONTH
+ INTERVAL dt_int MOD 100 - 1 DAY, '%Y%m%d') = dt_int;
你可以这样 set/unset SLQ_MODE。然后它工作
SELECT REPLACE(@@SQL_MODE, ',', '\n');
SET @@SQL_MODE = REPLACE(@@SQL_MODE, ',STRICT_TRANS_TABLES', '');
INSERT INTO table2(dt) SELECT * FROM (
SELECT DATE(str_to_date( dt_int , '%Y%m%d'))
FROM table1
WHERE date(str_to_date( dt_int, '%Y%m%d')) is not null
) as x;
另见 SQL_MODE
样本
创建表
mysql> CREATE TABLE `table1` (
-> `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
-> `dt_int` int(11) DEFAULT NULL,
-> PRIMARY KEY (`id`)
-> ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.04 sec)
mysql> INSERT INTO `table1` (`id`, `dt_int`)
-> VALUES
-> (1, 20200202),
-> (2, 20202020);
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> CREATE TABLE `table2` (
-> `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
-> `dt` date DEFAULT NULL,
-> PRIMARY KEY (`id`)
-> ) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.06 sec)
显示数据
mysql> SELECT DATE(str_to_date( dt_int , '%Y%m%d'))
-> FROM table1
-> WHERE date(str_to_date( dt_int, '%Y%m%d')) is not null;
+---------------------------------------+
| DATE(str_to_date( dt_int , '%Y%m%d')) |
+---------------------------------------+
| 2020-02-02 |
+---------------------------------------+
1 row in set, 2 warnings (0.00 sec)
运行 查询错误
mysql> INSERT INTO table2(dt)
-> SELECT DATE(str_to_date( dt_int , '%Y%m%d'))
-> FROM table1
-> WHERE date(str_to_date( dt_int, '%Y%m%d')) is not null;
ERROR 1411 (HY000): Incorrect datetime value: '20202020' for function str_to_date
mysql>
获取 SQL_MODE 并删除它
mysql>
mysql> SELECT REPLACE(@@SQL_MODE, ',', '\n');
+-------------------------------------------------------------------------------------------------------------------------------------------+
| REPLACE(@@SQL_MODE, ',', '\n') |
+-------------------------------------------------------------------------------------------------------------------------------------------+
| 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> SET @@SQL_MODE = REPLACE(@@SQL_MODE, ',STRICT_TRANS_TABLES', '');
Query OK, 0 rows affected, 1 warning (0.00 sec)
运行查询无误
mysql> INSERT INTO table2(dt) SELECT * FROM (
-> SELECT DATE(str_to_date( dt_int , '%Y%m%d'))
-> FROM table1
-> WHERE date(str_to_date( dt_int, '%Y%m%d')) is not null
-> ) as x;
Query OK, 1 row affected, 2 warnings (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 2
mysql>
我有一个奇怪的 MySQL INSERT SELECT 行为,我需要将 dt_int 从 TABLE2 转换为 TABLE1 中的日期时间 dt。
table 结构是
TABLE1
PK INT(11) -- auto increment
dt datetime
TABLE2
PK INT(11) -- auto increment
dt_int INT(11)
我有这样的插入 select 查询
INSERT INTO TABLE1(dt)
(
SELECT str_to_date(dt_int, '%Y%m%d')
FROM TABLE2
WHERE str_to_date(dt_int, '%Y%m%d') IS NOT NULL
)
如果 table 中的所有日期都有效,则可以正常工作。但是,如果 table 包含类似这样的数据
TABLE2
PK | dt_int
1 20201209
2 20202020
它会遇到错误代码 1411:函数 str_to_date.
的日期时间值“20202020”不正确内部select 语句returns 仅有效日期,但插入语句仍尝试转换那些被过滤的日期。为什么会这样?有什么我可以做的吗?
[已编辑] MySQL版本是5.7,引擎是InnoDB。当前托管在 Windows 环境中。
INSERT INTO table1
SELECT PK, CONCAT(dt_int DIV 10000, '-1-1')
+ INTERVAL dt_int MOD 10000 DIV 100 - 1 MONTH
+ INTERVAL dt_int MOD 100 - 1 DAY
FROM table2
WHERE 0 + DATE_FORMAT(CONCAT(dt_int DIV 10000, '-1-1')
+ INTERVAL dt_int MOD 10000 DIV 100 - 1 MONTH
+ INTERVAL dt_int MOD 100 - 1 DAY, '%Y%m%d') = dt_int;
你可以这样 set/unset SLQ_MODE。然后它工作
SELECT REPLACE(@@SQL_MODE, ',', '\n');
SET @@SQL_MODE = REPLACE(@@SQL_MODE, ',STRICT_TRANS_TABLES', '');
INSERT INTO table2(dt) SELECT * FROM (
SELECT DATE(str_to_date( dt_int , '%Y%m%d'))
FROM table1
WHERE date(str_to_date( dt_int, '%Y%m%d')) is not null
) as x;
另见 SQL_MODE
样本
创建表
mysql> CREATE TABLE `table1` (
-> `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
-> `dt_int` int(11) DEFAULT NULL,
-> PRIMARY KEY (`id`)
-> ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.04 sec)
mysql> INSERT INTO `table1` (`id`, `dt_int`)
-> VALUES
-> (1, 20200202),
-> (2, 20202020);
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> CREATE TABLE `table2` (
-> `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
-> `dt` date DEFAULT NULL,
-> PRIMARY KEY (`id`)
-> ) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.06 sec)
显示数据
mysql> SELECT DATE(str_to_date( dt_int , '%Y%m%d'))
-> FROM table1
-> WHERE date(str_to_date( dt_int, '%Y%m%d')) is not null;
+---------------------------------------+
| DATE(str_to_date( dt_int , '%Y%m%d')) |
+---------------------------------------+
| 2020-02-02 |
+---------------------------------------+
1 row in set, 2 warnings (0.00 sec)
运行 查询错误
mysql> INSERT INTO table2(dt)
-> SELECT DATE(str_to_date( dt_int , '%Y%m%d'))
-> FROM table1
-> WHERE date(str_to_date( dt_int, '%Y%m%d')) is not null;
ERROR 1411 (HY000): Incorrect datetime value: '20202020' for function str_to_date
mysql>
获取 SQL_MODE 并删除它
mysql>
mysql> SELECT REPLACE(@@SQL_MODE, ',', '\n');
+-------------------------------------------------------------------------------------------------------------------------------------------+
| REPLACE(@@SQL_MODE, ',', '\n') |
+-------------------------------------------------------------------------------------------------------------------------------------------+
| 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> SET @@SQL_MODE = REPLACE(@@SQL_MODE, ',STRICT_TRANS_TABLES', '');
Query OK, 0 rows affected, 1 warning (0.00 sec)
运行查询无误
mysql> INSERT INTO table2(dt) SELECT * FROM (
-> SELECT DATE(str_to_date( dt_int , '%Y%m%d'))
-> FROM table1
-> WHERE date(str_to_date( dt_int, '%Y%m%d')) is not null
-> ) as x;
Query OK, 1 row affected, 2 warnings (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 2
mysql>