Неявное приведение 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())