Mysql“;错误1292(22007):截断的时间值不正确:';2355:46:39.000000'&引用;插入期间

Mysql“;错误1292(22007):截断的时间值不正确:';2355:46:39.000000'&引用;插入期间,mysql,datetime,Mysql,Datetime,我目前正在从一个较小的表中计算一个datetime列和另一个datetime列的滞后变量之间的时间差。 然后将结果插入一个更大的最终表中。 这是一个过程的一部分,我有几个较小的表作为csv,每个表的滞后差异都必须计算并加载到最终表中(最终表约为20GB,12个较小的表约为2.5GB) 我已经在没有滞后变量的情况下单独插入了好几次,一切都很好。 然而,在表6(共12页)中的某个地方,我现在得到了以下错误,我无法找出原因: ERROR 1292 (22007): Truncated incorrec

我目前正在从一个较小的表中计算一个datetime列和另一个datetime列的滞后变量之间的时间差。 然后将结果插入一个更大的最终表中。 这是一个过程的一部分,我有几个较小的表作为csv,每个表的滞后差异都必须计算并加载到最终表中(最终表约为20GB,12个较小的表约为2.5GB)

我已经在没有滞后变量的情况下单独插入了好几次,一切都很好。 然而,在表6(共12页)中的某个地方,我现在得到了以下错误,我无法找出原因:

ERROR 1292 (22007): Truncated incorrect time value: '2355:46:39.000000'
我可以提供一个适用于其余表格的测试示例:

DROP TABLE IF EXISTS single_test;

CREATE TABLE single_test(
medallion VARCHAR(64),
hack_license VARCHAR(64),
pickup_datetime DATETIME,
dropoff_datetime DATETIME,
id  INT NOT NULL,
PRIMARY KEY (id) 
);
INSERT INTO single_test VALUES
('a', '1' , '2013-01-06 00:18:35','2013-01-06 02:10:33',1),
('a', '1' , '2013-01-06 02:40:58','2013-01-06 03:40:01',2),
('b', '1' , '2013-01-06 04:07:21','2013-01-06 05:00:41',3),
('c', '1' , '2013-01-07 13:12:08','2013-01-07 13:32:27',4),
('a', '2', '2013-01-06 03:50:30','2013-01-06 04:22:13',5),
('a', '2', '2013-01-06 04:41:23','2013-01-06 04:57:04',6),
('d', '2', '2013-01-07 12:22:56','2013-01-07 13:02:14',7),
('d', '3', '2013-01-07 13:03:24','2013-01-07 15:47:31',8)
;


CREATE TABLE final_test(
medallion VARCHAR(64),
hack_license VARCHAR(64),
pickup_datetime DATETIME,
dropoff_datetime DATETIME,
id  INT NOT NULL,
delta VARCHAR(20),
current_dropoff DATETIME,
current_hack VARCHAR(64),
PRIMARY KEY (id) 
);

SET @quot= '000-00-00 19:19:19';
SET @current_hack = ''; 
INSERT INTO final_test
SELECT medallion, hack_license, pickup_datetime, dropoff_datetime, id,
IF(@current_hack = hack_license,TIMEDIFF(pickup_datetime,  @quot),NULL) as delta,
@quot:= dropoff_datetime current_dropoff, @current_hack:= hack_license
FROM single_test ORDER BY hack_license, pickup_datetime;
结果如下所示:

SELECT * FROM final_test;
+-----------+--------------+---------------------+---------------------+----+-----------------+---------------------+--------------+
| medallion | hack_license | pickup_datetime     | dropoff_datetime    | id | delta           | current_dropoff     | current_hack |
+-----------+--------------+---------------------+---------------------+----+-----------------+---------------------+--------------+
| a         | 1            | 2013-01-06 00:18:35 | 2013-01-06 02:10:33 |  1 | NULL            | 2013-01-06 02:10:33 | 1            |
| a         | 1            | 2013-01-06 02:40:58 | 2013-01-06 03:40:01 |  2 | 00:30:25.000000 | 2013-01-06 03:40:01 | 1            |
| b         | 1            | 2013-01-06 04:07:21 | 2013-01-06 05:00:41 |  3 | 00:27:20.000000 | 2013-01-06 05:00:41 | 1            |
| c         | 1            | 2013-01-07 13:12:08 | 2013-01-07 13:32:27 |  4 | 32:11:27.000000 | 2013-01-07 13:32:27 | 1            |
| a         | 2            | 2013-01-06 03:50:30 | 2013-01-06 04:22:13 |  5 | NULL            | 2013-01-06 04:22:13 | 2            |
| a         | 2            | 2013-01-06 04:41:23 | 2013-01-06 04:57:04 |  6 | 00:19:10.000000 | 2013-01-06 04:57:04 | 2            |
| d         | 2            | 2013-01-07 12:22:56 | 2013-01-07 13:02:14 |  7 | 31:25:52.000000 | 2013-01-07 13:02:14 | 2            |
| d         | 3            | 2013-01-07 13:03:24 | 2013-01-07 15:47:31 |  8 | NULL            | 2013-01-07 15:47:31 | 3            |
+-----------+--------------+---------------------+---------------------+----+-----------------+---------------------+--------------+
8 rows in set (0,00 sec)

相反,错误消息没有多大意义,因为我希望TIMEDIFF截断任何无效输入:

# Extremely Large difference
SELECT TIMEDIFF("2013-01-01 19:00:00","1900-01-01 19:00:00");
+-------------------------------------------------------+
| TIMEDIFF("2013-01-01 19:00:00","1900-01-01 19:00:00") |
+-------------------------------------------------------+
| 838:59:59                                             |
+-------------------------------------------------------+
1 row in set, 1 warning (0,00 sec)

# Invalid/ unrealistic datetime format due to to high/ to low values
SELECT TIMEDIFF("2013-01-01 19:00:00","000-00-00 19:19:19");
+------------------------------------------------------+
| TIMEDIFF("2013-01-01 19:00:00","000-00-00 19:19:19") |
+------------------------------------------------------+
| 838:59:59                                            |
+------------------------------------------------------+
1 row in set, 1 warning (0,00 sec)

# Invalid/ unrealistic datetime format due to character in values
SELECT TIMEDIFF("2013-01-01 19:00:00","000-00-00T 19:19:19");
+-------------------------------------------------------+
| TIMEDIFF("2013-01-01 19:00:00","000-00-00T 19:19:19") |
+-------------------------------------------------------+
| NULL                                                  |
+-------------------------------------------------------+
1 row in set, 1 warning (0,00 sec)

我正在使用Mysql 5.7

我还搜索了较小的数据,查找字母表中的无效字符,但什么也没找到

致意


PS:我知道这个SO线程,但它没有从官方MySQL文档中提供任何帮助:

DATETIME类型用于同时包含日期和时间的值 部分。MySQL检索并显示“YYYY-MM-DD”中的日期时间值 hh:mm:ss'格式。支持的范围为“1000-01-01 00:00:00”到 “9999-12-3123:59:59”

2355:46:39.00000显然超出了支持的00:00:00-23:59:59范围

| TIMEDIFF("2013-01-01 19:00:00","1900-01-01 19:00:00") |
+-------------------------------------------------------+
| 838:59:59  
如果此查询的预期结果是00:00:00,而不是838:59:59,请尝试以下操作:

TIMEDIFF(TIME("2013-01-01 19:00:00"),TIME("1900-01-01 19:00:00"));

来源:

可以使用以下脚本复制该问题:

create table test(
  tdiff varchar(20)
);

set @dt1 = '1900-01-01 19:00:00';
set @dt2 = '2013-01-01 19:00:00';

select TIMEDIFF(@dt2, @dt1);

insert into test (tdiff) select TIMEDIFF(@dt2, @dt1);
SELECT语句返回
838:59:59
,但具有相同表达式的INSERT语句将引发错误:

错误:ER\U截断\U错误\U值:截断错误的时间值: “990552:00:00”

您将遇到类似的查询问题,如

insert into test (tdiff) select cast('abc' as char(2));

而相应的SELECT语句将返回
ab
NULL
,且无错误

错误的原因是模式。如果这种行为有道理,我们可以争辩,但我怀疑它是否会改变

那你能做什么呢

1.使用插入忽略。。 在
INSERT
之后使用
IGNORE
将这些错误转换为警告。这似乎是最简单的方法

2.禁用严格转换表模式 您可以仅对一条语句禁用
STRICT\u TRANS\u TABLES
模式:

set @old_sql_mode = @@sql_mode;
set session sql_mode = replace(@@sql_mode, 'STRICT_TRANS_TABLES', '');

<your INSERT statement here>;

set session sql_mode = @old_sql_mode;
4.节省秒而不是时间 这将是我喜欢的解决方案。使用
TIMESTAMPDIFF()
以秒为单位获取差值:

insert into test (tdiff) select timestampdiff(second, @dt1, @dt2);

请注意,
timesdiff()
使用的参数顺序与
TIMEDIFF()
不同。因此,如果您想得到一个积极的结果,最短的日期时间值应该排在第一位。

如何重现该问题?你的密码。请发布
select@@sql\u模式的结果这里有一个较短的可重复示例:错误是否有意义。对我来说没有意义的是,它是在insert语句中抛出的,而不是在select语句中抛出的。太棒了!这也是我的问题:为什么我会得到一个错误,将插入查询而不是截断的值插入。你的答案并不能解决问题,但缩小了问题的范围,并提供了一个可重复的例子!也许你或我应该在
select@@sql\u模式的另一个threadresult中,根据你的小提琴,发布一个更精确的问题“|@@sql|模式|仅|完整|分组|依据、严格的|转换|表、不|零|输入|日期、不|零|日期、按|零除|的错误|不|自动|创建|用户、不|引擎| | | `此代码引发Syntax(“2013-01-01 19:00:00”);时间(“1900-01-01 19:00:00”);“``我也知道2355:46:39.00000超出了范围。问题是为什么我会收到一个错误,停止整个INSERT语句,而不是像您的示例中那样截断值”```` TIMEDIFF(“2013-01 19:00:00”,“1900-01-01 19:00:00”)|+---------------------------------------------------------------+|838:59:59``将是完美的好吧,我登录我的MySQL droplet并选择TIMEDIFF(TIME(“2013-01-01 19:00:00”)、TIME(“1900-01-01 19:00:00”);在0.0004秒内按预期返回00:00:00。查看此小提琴:如果继续截断“2355:46:39.00000”中的尾随零“使用其他一些MySQL函数,它的数值仍将超出数据类型的范围。哇!多么惊人的回答!我想我从你们的每一个解决方案中学到了新的东西!非常感谢你
set @old_sql_mode = @@sql_mode;
set session sql_mode = replace(@@sql_mode, 'STRICT_TRANS_TABLES', '');

<your INSERT statement here>;

set session sql_mode = @old_sql_mode;
insert into test (tdiff) select 
  case when abs(timestampdiff(hour, @dt2, @dt1)) < 839
    then TIMEDIFF(@dt2, @dt1)
    else 'out of range'
  end
insert into test (tdiff) select timestampdiff(second, @dt1, @dt2);