Неявное приведение from () к полю даты

У меня проблема с MySQL 5.1. Тип данных datetime неявно приводится к столбцу даты.

 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.

Проблема появляется только при неявном приведении от даты к дате. Никто не сталкивался с этой проблемой или не знает, как ее решить? Я знаю, что не лучше использовать 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() или вернуться к предыдущей версии.

На самом деле, вы можете скомпилировать свою собственную версию и либо отменить "исправление ошибки", либо переопределить функцию NOW().

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

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

Интересный момент из этого документа (не уверен, что это ваша проблема, но это может быть): 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()) и покончим с этим.

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

SELECT * FROM my_table WHERE DATE(my_date_field) = DATE(NOW())
Другие вопросы по тегам