插入期间Mysql“错误1292(22007):截断了错误的时间值:'2355:46:39.000000'”

时间:2019-08-06 18:29:56

标签: mysql datetime

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

我之前已经完成了几次没有滞后变量的单独插入,一切都很好。 但是,在表12中的6中,现在出现以下错误,我无法弄清原因:

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截断任何无效的输入,因此ERROR消息没有多大意义:

# 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线程,但是它没有提供任何帮助Error Code: 1292. Truncated incorrect time value

2 个答案:

答案 0 :(得分:1)

可以使用以下脚本重现该问题:

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_TRUNCATED_WRONG_VALUE:截断了错误的时间值:   '990552:00:00'

诸如此类的查询会遇到类似的问题

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

insert into test (tdiff) select '9999-12-31' + interval 1 day;

而相应的SELECT语句将返回abNULL而没有错误。

错误的原因是STRICT_TRANS_TABLES模式。我们可以争论一下,如果这种行为有意义的话-但我怀疑这种行为是否会改变。

那你能做什么?

1。使用INSERT IGNORE ..

insert ignore into test (tdiff) select TIMEDIFF(@dt2, @dt1);

IGNORE之后使用INSERT会将这些错误转换为警告。这似乎是最简单的方法。

2。禁用STRICT_TRANS_TABLES模式

您可以仅针对一条语句禁用STRICT_TRANS_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;

3。使用条件表达式

由于有效范围是从-838:59:59+838:59:59,因此我们可以检查小时数的绝对差是否小于839-否则返回其他值:

insert into test (tdiff) select 
  case when abs(timestampdiff(hour, @dt2, @dt1)) < 839
    then TIMEDIFF(@dt2, @dt1)
    else 'out of range'
  end

4。节省时间而不是时间

这是我首选的解决方案。使用TIMESTAMPDIFF()以秒为单位计算差异:

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

请注意,TIMESTAMPDIFF()使用的参数顺序与TIMEDIFF()不同。因此,如果要获得肯定的结果,则应将最小的DATETIME值排在第一位。

答案 1 :(得分:0)

摘自MySQL官方文档:

  

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

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

class BlogListing(BaseListing):
    subpage_types = ['BlogPost']
    template = 'listing.html'

如果此查询的预期结果是 00:00:00 ,而不是 838:59:59 ,请尝试以下操作:

| TIMEDIFF("2013-01-01 19:00:00","1900-01-01 19:00:00") |
+-------------------------------------------------------+
| 838:59:59  

来源:https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_time