插入时出现日期时间字段溢出错误

Datetime field overflow error while inserting

提问人:Oleksandr Zakharchenko 提问时间:11/10/2023 最后编辑:Oleksandr Zakharchenko 更新时间:11/10/2023 访问量:89

问:

我有一张桌子test_a

CREATE TABLE `test_a` (
  `CUSTOMER_RK`         int         DEFAULT NULL,
  `CUSTOMER_STATUS`     varchar(45) DEFAULT NULL,
  `EFFECTIVE_FROM_DTTM` date        DEFAULT NULL,
  `EFFECTIVE_TO_DTTM`   date        DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

像这样填充:

CUSTOMER_RK CUSTOMER_STATUS EFFECTIVE_FROM_DTTM EFFECTIVE_TO_DTTM
1 一个 2004-01-20 2015-02-23
1 B 2016-02-24 2016-05-17
1 一个 2017-05-18 9999-12-31
2 B 1998-09-01 2018-09-04
2 一个 2018-09-05 2018-09-06
2 B 2019-09-07 2019-09-07
2 一个 2019-09-08 9999-12-31

尝试使用以下代码在我的表中插入此选择查询的结果:

INSERT INTO test_a (
    CUSTOMER_RK, CUSTOMER_STATUS, EFFECTIVE_FROM_DTTM, EFFECTIVE_TO_DTTM
)
SELECT
    CUSTOMER_RK,
    CUSTOMER_STATUS,
    EFFECTIVE_FROM_DTTM,
    EFFECTIVE_TO_DTTM
FROM
    (
        SELECT
            CUSTOMER_RK,
            CUSTOMER_STATUS,
            DATE_ADD( EFFECTIVE_TO_DTTM, INTERVAL 1 DAY ) AS EFFECTIVE_FROM_DTTM,
            DATE_SUB( LEAD( EFFECTIVE_FROM_DTTM, 1, '9999-12-31' ) OVER ( ORDER BY EFFECTIVE_FROM_DTTM ), INTERVAL 1 DAY ) AS EFFECTIVE_TO_DTTM

        FROM
            test_a AS a1
        WHERE
            CUSTOMER_RK = 1
    ) AS a2
WHERE
    EFFECTIVE_FROM_DTTM < EFFECTIVE_TO_DTTM;

但是出现此错误:

18:53:59    INSERT INTO test_a (CUSTOMER_RK, CUSTOMER_STATUS, EFFECTIVE_FROM_DTTM, EFFECTIVE_TO_DTTM) SELECT CUSTOMER_RK, CUSTOMER_STATUS, EFFECTIVE_FROM_DTTM, EFFECTIVE_TO_DTTM FROM ( SELECT CUSTOMER_RK, CUSTOMER_STATUS, DATE_ADD(EFFECTIVE_TO_DTTM, INTERVAL 1 DAY) AS EFFECTIVE_FROM_DTTM,  DATE_SUB(LEAD(EFFECTIVE_FROM_DTTM, 1, '9999-12-31') OVER (ORDER BY EFFECTIVE_FROM_DTTM), INTERVAL 1 DAY) AS EFFECTIVE_TO_DTTM FROM test_a AS a1 WHERE CUSTOMER_RK = 1 ) AS a2 WHERE EFFECTIVE_FROM_DTTM < EFFECTIVE_TO_DTTM

Error Code: 1441. Datetime function: datetime field overflow    0.000 sec

为什么我会收到此错误?

更新:

MySQL版本:8.0.34

sql_mode:'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'

结果是SELECT '9999-12-31' + INTERVAL 1 DAY;NULL

mysql 日期 sql-insert

评论

1赞 Dai 11/10/2023
DATE_ADD( EFFECTIVE_TO_DTTM, INTERVAL 1 DAY )将增加 1 天,该天将溢出。您可能应该使用 in .9999-12-31NULLdefaultLEAD()
2赞 Satanicpuppy 11/10/2023
Y10k 漏洞的第一个受害者
0赞 Oleksandr Zakharchenko 11/10/2023
尝试过但出现相同的错误LEAD(EFFECTIVE_FROM_DTTM, 1, NULL)
0赞 Dai 11/10/2023
@OleksandrZakharchenko 请在 dbfiddle.uk 上重新创建问题并在此处发布链接

答:

0赞 user1191247 11/10/2023 #1

我无法弄清楚MySQL版本和sql_mode组合会导致这种情况。请在您的问题中添加以下内容,因为我很想知道:

  1. MySQL 版本(SELECT VERSION();)
  2. sql_mode (SELECT @@sql_mode;)
  3. 结果SELECT '9999-12-31' + INTERVAL 1 DAY;

更新:感谢您将上述答案添加到您的问题中。我不知道昨晚我看这个时在做什么/想什么,但它很容易重现。

您可以通过对有问题的值执行 NULLing 来避免它。

改变

DATE_ADD( EFFECTIVE_TO_DTTM, INTERVAL 1 DAY ) AS EFFECTIVE_FROM_DTTM,

DATE_ADD( NULLIF(EFFECTIVE_TO_DTTM, '9999-12-31'), INTERVAL 1 DAY ) AS EFFECTIVE_FROM_DTTM,

恕我直言,更好的选择是在未知时存储更合适的值,例如 .EFFECTIVE_TO_DTTMNULL

这是一个 db<>小提琴

评论

0赞 Oleksandr Zakharchenko 11/10/2023
将您提出的问题添加到问题中
0赞 user1191247 11/10/2023
谢谢。我添加了一个 db<>fiddle