2010-04-27 2 views
1

У меня проблема с MySQL 5.1. Тип данных datetime не неявно отбрасывается, чтобы соответствовать столбцу даты.Неявное отбрасывание от now() до поля даты

SELECT * FROM my_table WHERE my_date_field = NOW() 

Этот запрос не возвращает ни одной строки, используя MySQL 5.1, но хорошо работает с версией 5.0. Если мы используем CURDATE() вместо NOW(), он работает как в MySQL 5.0, так и в MySQL 5.1. Если бросок является явным (CAST(NOW() AS DATE)), он также работает как в MySQL 5.0, так и в MySQL 5.1.

Проблема возникает только при неявном приведении из datetime на дату. Разве никто не сталкивался с этой проблемой или не знает, как решить эту проблему? Я знаю, что не лучше использовать NOW() вместо CURTIME(), но здесь это не вопрос. В настоящее время он используется в приложении, и цель состоит в том, чтобы не переписывать все.

Спасибо!

ответ

3

Это было исправлено в MySQL 5.1.17, чтобы CurDate(), чтобы оценить менее NOW() при хранении в столбце DATE.

Теперь, сравнивая DATE с DATETIME, они сравниваются как DATETIME. Когда DATE передается в DATETIME, он имеет нулевой час.

Если my_date_field является '2010-01-01' И NOW() является '2010-01-01 05:01:01', когда они сравниваются, my_date_field повышен до '2010-01-01 00:00:00', что явно меньше, чем '2010-01-01 05:01:01'.

Первоначально, когда на левой стороне была колонка, продвижение с DATE на DATETIME не произошло. Однако, по-видимому, они думали, что более последовательно поддерживать его.

Извините, но вам повезло, что он работал раньше. Дата, которая имеет нулевой час, должна оцениваться менее чем за ту же дату с ненулевым часом.

К сожалению, нет способа отключить это «исправление ошибок». Ваше единственное решение - изменить NOW() на CURDATE() или вернуться к предыдущей версии.

На самом деле вы можете скомпилировать свою версию и отменить «исправление ошибок» или переопределить функцию «СЕЙЧАС»().

+0

Я думаю, что вы отлично ответили на вопрос. Благодаря! – Savageman

+0

+1 для идеального ответа. –

1

Поведение имеет смысл, потому что NOW() имеет тип DATETIME и CURDATE() типа DATE.

Что касается того, почему переменные передаются в одной версии сервера, а не в другой - это больше похоже на разницу в server modes, то есть на один экземпляр, где литье не является более строгим, чем другое.

Интересный момент из этого документа (не уверен, является ли ваша проблема, но это может быть): ALLOW_INVALID_DATES:

Этот режим реализован в MySQL 5.0.2. До версии 5.0.2 это был режим обработки дат MySQL по умолчанию. Начиная с 5.0.2, сервер требует, чтобы значения месяца и дня были законными, а не только в диапазоне от 1 до 12 и от 1 до 31 соответственно. При отключенном строгом режиме недопустимые даты, такие как «2004-04-31», преобразуются в «0000-00-00» и генерируется предупреждение. При включенном строгом режиме недопустимые даты генерируют ошибку. Чтобы разрешить такие даты, включите ALLOW_INVALID_DATES.

В любом случае, я не уверен, имеет ли смысл копаться в списках изменений, пытаясь выяснить, что изменилось. Я бы старался, чтобы поведение работало в обеих ситуациях (т. Е. Если я правильно вас понимаю, используйте CURDATE()) и делайте это с ним.

+0

Ваша ссылка привела меня к [show-warning] [1]. Я буду использовать его завтра, чтобы проверить, есть ли в этом конкретном случае. [1]: http://dev.mysql.com/doc/refman/5.0/en/show-warnings.html – Savageman

0

сравнить только часть даты вашего столбца даты и времени:

SELECT * FROM my_table WHERE DATE(my_date_field) = DATE(NOW()) 
+0

Спасибо, но мы не хотим переписывать все приложение. – Savageman

+0

, вы можете затем изменить поля 'datetime' на' date' (потерять информацию о времени) или не обновить (плохое решение). переписывание большого количества кода происходит во время разработки программного обеспечения, нет никакого способа обойти его – knittl