MySQL INSERT INTO SELECT не соответствующие записи запускаются функцией str_to_date - PullRequest
0 голосов
/ 03 марта 2020

У меня странное поведение MySQL INSERT SELECT, где мне нужно преобразовать dt_int из TABLE2 в дату и время dt в TABLE1.

Структура таблицы:

TABLE1
PK INT(11) -- auto increment
dt datetime

TABLE2
PK INT(11)  -- auto increment
dt_int INT(11)

У меня есть запрос на вставку, подобный этому

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
)

Работает нормально, если все даты в таблице действительны. Однако, если таблица состоит из данных, подобных этим

TABLE2
PK   |   dt_int
1        20201209
2        20202020

, это приведет к появлению кода ошибки 1411: неверное значение даты-времени '20202020' для функции str_to_date.

Внутренние операторы выбора возвращают только действительные даты, но операторы вставки все еще пытаются преобразовать дату для тех, которые отфильтрованы. Почему это происходит? Могу ли я что-нибудь сделать?

[Отредактировано] MySQL версия 5.7 и двигатель InnoDB. В настоящее время размещен в среде Windows.

Ответы [ 2 ]

0 голосов
/ 03 марта 2020

Вы можете установить / сбросить 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 и удалить it

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>
0 голосов
/ 03 марта 2020
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;

скрипка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...