Неявное приведение from () к полю даты - PullRequest
1 голос
/ 27 апреля 2010

У меня проблема с 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 ]

3 голосов
/ 27 апреля 2010

Это было исправлено в 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 ().

1 голос
/ 27 апреля 2010

Поведение имеет смысл, поскольку 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()) и покончите с этим.

0 голосов
/ 27 апреля 2010

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

SELECT * FROM my_table WHERE DATE(my_date_field) = DATE(NOW())
...