【问题标题】:MySQL STR_TO_DATE gives invalid results?MySQL STR_TO_DATE 给出无效结果?
【发布时间】:2010-09-08 16:40:26
【问题描述】:

我在 Win64 上使用 MySQL 5.1.49。我们也在 Solaris 机器上看到了以下行为。这是我的测试表:

CREATE TABLE `date_test` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `date1` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `Index_2` (`date1`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

mysql> select * from date_test;
+----+---------------------+
| id | date1               |
+----+---------------------+
|  1 | 2010-09-01 01:00:00 |
|  2 | 2010-09-06 23:59:59 |
|  3 | 2010-09-07 01:00:00 |
+----+---------------------+
3 rows in set (0.00 sec)

以下查询运行正确:

mysql> SELECT * FROM date_test WHERE
           date1 > DATE_SUB('2010-10-06 23:59:59', interval 1 month);
+----+---------------------+
| id | date1               |
+----+---------------------+
|  3 | 2010-09-07 01:00:00 |
+----+---------------------+
1 row in set (0.00 sec)

但是,如果我在其中抛出 STR_TO_DATE(),则查询不会按预期运行:

mysql> SELECT * FROM date_test WHERE
         date1 > DATE_SUB(
            STR_TO_DATE('10/06/2010 23:59:59', '%m/%d/%Y %T'), interval 1 month
         );
+----+---------------------+
| id | date1               |
+----+---------------------+
|  1 | 2010-09-01 01:00:00 |
|  2 | 2010-09-06 23:59:59 |
|  3 | 2010-09-07 01:00:00 |
+----+---------------------+
3 rows in set (0.00 sec)

这里发生了非常奇怪的行为。您可以将任何日期与STR_TO_DATE() 函数一起使用,该查询将返回表中的所有记录(甚至在很远的将来)。文档表明STR_TO_DATE() 应该返回一个 DATETIME,这应该是DATE_SUB() 的有效输入,但显然有些问题。

附带说明,运行 SELECT STR_TO_DATE('10/06/2010 23:59:59', '%m/%d/%Y %T') 会返回第一个查询的确切输入 2010-10-06 23:59:59。此外,如果您使用TIMESTAMP() 函数或CAST(STR_TO_DATE() AS DATETIME)STR_TO_DATE() 函数的结果包装在问题查询中,则结果将按预期返回。但这真的有必要吗?

我想我在这里遗漏了一些东西。任何人都可以解释一下吗?

更新

这绝对看起来像一个错误。在 5.1.36 版上:

-- interval of month or day does not work:
SELECT '1999-04-01 23:34:12' > DATE_SUB(STR_TO_DATE('09/06/2010 23:59:59', '%m/%d/%Y %T'), INTERVAL 1 MONTH);
--->  1   (incorrect)
-- using 720 hours (30 days) works:
SELECT '1999-04-01 23:34:12' > DATE_SUB(STR_TO_DATE('09/06/2010 23:59:59', '%m/%d/%Y %T'), INTERVAL 720 HOUR);
--->  0
-- wrapping in TIMESTAMP( ) works:
SELECT '1999-04-01 23:34:12' > DATE_SUB(TIMESTAMP(STR_TO_DATE('09/06/2010 23:59:59', '%m/%d/%Y %T')), INTERVAL 1 MONTH);
--->  0

在 5.0.51a-log 版本上,一切都按预期工作:

SELECT '1999-04-01 23:34:12' > DATE_SUB(STR_TO_DATE('09/06/2010 23:59:59', '%m/%d/%Y %T'), INTERVAL 1 MONTH);
--->  0  
SELECT '1999-04-01 23:34:12' > DATE_SUB(STR_TO_DATE('09/06/2010 23:59:59', '%m/%d/%Y %T'), INTERVAL 720 HOUR);
--->  0
SELECT '1999-04-01 23:34:12' > DATE_SUB(TIMESTAMP(STR_TO_DATE('09/06/2010 23:59:59', '%m/%d/%Y %T')), INTERVAL 1 MONTH);
--->  0

【问题讨论】:

  • 能否请您发布SHOW CREATE TABLE date_test的输出?
  • 是的,这是一个错误。查看我的帖子更新。

标签: mysql datetime date


【解决方案1】:

这真的很奇怪,似乎是一个错误。

我设法将其归结为:

SELECT  '0000-00-00 00:00:20' > STR_TO_DATE('10/06/2010 23:59:59', '%m/%d/%Y %T') - INTERVAL 1 MONTH,
        '0000-00-00 00:00:21' > STR_TO_DATE('10/06/2010 23:59:59', '%m/%d/%Y %T') - INTERVAL 1 MONTH

,这意味着第二个表达式中的年份与第一个表达式中的秒数进行比较。

可能有一些奇怪的 DATEINTEGER 介于两者之间。

请注意,如果您添加 + INTERVAL 0 SECONDS,则表达式将转换为正确的 DATETIME 并且运行良好。

我会将它作为错误发布到MySQL

更新:

这已经作为bug 提交,并且一周前发布了一个补丁来修复它。

【讨论】:

    猜你喜欢
    • 2014-07-11
    • 1970-01-01
    • 2014-07-12
    • 2017-10-25
    • 2014-12-01
    • 1970-01-01
    • 2019-05-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多