← К оглавлению занятия

🐛 Типичные ошибки

⚡ Кратко: ошибки

  • Сравнивать даты как строки — результат может быть непредсказуемым.
  • Путать порядок аргументов в 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
);