Сравнивать даты как строки — результат может быть непредсказуемым.
Путать порядок аргументов в DATEDIFF.
Игнорировать часовой пояс TIMESTAMP.
Использовать VARCHAR в CAST вместо CHAR.
Путать спецификаторы %m (месяц) и %M (название месяца).
1
Ошибка: сравнение дат как строк
Строковое сравнение дат работает только при формате YYYY-MM-DD. Если формат другой, результат будет неверным.
-- Работает случайно, потому что формат совпадает
SELECT * FROM orders WHERE order_date > '2024-01-01';
-- Опасно: '01-12-2024' строково больше '12-01-2023'
SELECT * FROM orders WHERE formatted_date > '12-01-2023';
Как исправить: сравнивайте значения типа DATE или DATETIME, а не отформатированные строки.
SELECT * FROM orders WHERE order_date > CAST('2024-01-01' AS DATE);
2
Ошибка: неправильный порядок аргументов DATEDIFF
В MySQL DATEDIFF(date1, date2) возвращает date1 - date2. Перепутанный порядок даст отрицательный результат.
-- Неправильно: получим отрицательные дни
SELECT DATEDIFF(order_date, shipped_date) AS days FROM orders;
-- Правильно
SELECT DATEDIFF(shipped_date, order_date) AS days_to_ship FROM orders;
3
Ошибка: игнорирование часового пояса TIMESTAMP
TIMESTAMP хранит время в UTC и переводит его в часовой пояс сессии при выводе. Разные клиенты могут видеть разные значения.
-- Проверьте настройки сессии
SELECT @@session.time_zone;
SET time_zone = '+03:00';
Как исправить: если часовой пояс критичен, используйте DATETIME с явным хранением зоны или храните зону отдельно.
4
Ошибка: CAST(... AS VARCHAR) в MySQL
В MySQL CAST не принимает VARCHAR(n) для указания длины строки. Нужно использовать CHAR(n).
-- Ошибка в MySQL
SELECT CAST(customer_id AS VARCHAR(10)) FROM orders;
-- Правильно
SELECT CAST(customer_id AS CHAR(10)) FROM orders;
5
Ошибка: путаница в спецификаторах DATE_FORMAT
%M — полное название месяца, %m — номер месяца. %M — минуты, %i — тоже минуты. Легко перепутать.
-- Неправильно: %M даст August, а не 08
SELECT DATE_FORMAT(NOW(), '%d-%M-%Y');
-- Правильно
SELECT DATE_FORMAT(NOW(), '%d-%m-%Y');
6
Ошибка: выбор TIMESTAMP для далёкого будущего
Диапазон TIMESTAMP заканчивается 2038-01-19. Для долгосрочных дат используйте DATETIME.
-- Опасно: значение за пределами диапазона
CREATE TABLE licenses (
id INT PRIMARY KEY,
expires_at TIMESTAMP
);
-- Лучше
CREATE TABLE licenses (
id INT PRIMARY KEY,
expires_at DATETIME
);