我在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
。此外,如果使用STR_TO_DATE()
函数或TIMESTAMP()
将CAST(STR_TO_DATE() AS DATETIME)
函数的结果包装在问题查询中,则会按预期返回结果。但这真的有必要吗?
我想我在这里遗漏了一些东西。任何人都可以放弃任何光明吗?
更新
这绝对看起来像一个bug。在版本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
答案 0 :(得分:2)
这真的很奇怪,似乎是一个错误。
我设法把它归结为:
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
,表示第二个表达式中的年份与第一个表达式中的秒数进行比较。
两者之间可能存在一些奇怪的DATE
到INTEGER
。
请注意,如果您添加+ INTERVAL 0 SECONDS
,表达式会被转换为正确的DATETIME
并且运行良好。
我会将其作为错误发布到MySQL
。
<强>更新强>
这已经作为bug提交,并且一周前发布了修补程序以修复它。