- 17 октября 2026
- 12 минут
- 6
Статью подготовили специалисты образовательного сервиса Zaochnik.
Операции с датами и временем в SQL
Работа с датами SQL включает набор функций и операторов для получения текущих значений даты и времени, выполнения арифметики с датами, а также преобразований между форматами. Точное выполнение таких операций требует понимания типов, форматов интервалов и особенностей функций SQL.
Дата - это значение, представляющее календарный день, обычно в формате YYYY-MM-DD.
Временной интервал - это величина времени, выраженная в единицах, таких как секунды, минуты, часы, дни, месяцы, годы, используемая для арифметических операций с датами.
Получение текущих даты и времени
В SQL для получения текущей даты, времени и их комбинации используются специализированные функции. Для получения текущей даты без времени применяются функции CURDATE() и CURRENT_DATE(). Формат вывода - строка в виде "YYYY-MM-DD". Обе функции эквивалентны и возвращают дату сервера с точностью до суток.
Для получения текущего времени без даты существуют функции CURTIME() и CURRENT_TIME(). Они возвращают строку в формате "HH:MM:SS", отражая время сервера с точностью до секунды.
Функции для получения текущих даты и времени с точностью до секунды включают NOW(), SYSDATE() и CURRENT_TIMESTAMP. Они выводят значение в формате "YYYY-MM-DD HH:MM:SS". Разница между NOW() и SYSDATE() заключается в моменте вычисления: NOW() фиксирует время на момент начала запроса, SYSDATE() – на момент вызова функции. CURRENT_TIMESTAMP эквивалентен NOW() по стандарту SQL.
Текущий формат вывода даты и времени зависит от настроек локали и сервера, но общепринят формат ISO 8601 с разделителем пробелом между датой и временем.
SELECT CURDATE(); // Возвращает: 2016-08-28
SELECT CURTIME(); // Возвращает: 19:29:54
SELECT NOW(); // Возвращает: 2016-08-28 19:29:54
Важная особенность: CURDATE() и CURRENT_DATE() не возвращают временной части, что полезно для фильтрации по датам без учета времени. Использование NOW() для таких целей требует дополнительного преобразования или обрезки времени. Неправильное применение временных функций ведет к ошибкам выборок, особенно при сравнении с фиксированными датами.
Прибавление и вычитание временного интервала
В SQL доступны три способа выполнить арифметические операции с датами: функции DATE_ADD(), ADDDATE() и операторы с использованием выражений вида "дата + INTERVAL выражение тип". Аналогично для вычитания используются DATE_SUB(), SUBDATE() и выражения с "дата - INTERVAL выражение тип".
Аргумент исходная_дата представляет дату или datetime, к которому добавляется или вычитается интервал. Интервал задается в виде строки или числа, дополненного указанием типа, например: SECOND, MINUTE, HOUR, DAY, MONTH, YEAR, YEAR_MONTH, DAY_MICROSECOND и др. Тип определяет единицы измерения и интерпретацию выражения.
Интерпретация выражения зависит от типа. Например, строка '3:24' при типе MINUTE_SECOND трактуется как 3 минуты 24 секунды. Если тип отсутствует или неясен, возможны ошибки в интерпретации, что приводит к неверному результату. Типы YEAR_MONTH и DAY_SECOND позволяют использовать выражения в формате 'год-месяц' и 'день час:минуты:секунды' соответственно.
SELECT '2016-09-10 23:59:59' + INTERVAL 1 SECOND; // Возвращает: 2016-09-11 00:00:00
SELECT DATE_ADD('2016-09-10 23:59:59', INTERVAL 1 SECOND); // Тот же результат
SELECT ADDDATE('2016-09-10 23:59:59', INTERVAL 1 SECOND); // Тот же результат
Такая операция практична для инкрементов времени. Однако частой ошибкой является неправильный тип интервала, например, указание '1-6' без указания YEAR_MONTH, что приведет к ошибке синтаксиса или неверной интерпретации.
SELECT DATE_SUB('2016-09-10 23:59:59', INTERVAL '1-6' YEAR_MONTH); // Результат: 2015-03-10 23:59:59
SELECT '2016-09-10 23:59:59' - INTERVAL '1-6' YEAR_MONTH; // То же самое
При вычитании интервала, если результирующая дата выйдет за пределы допустимого диапазона даты SQL (например, до 1000-01-01), операция завершится ошибкой. В MySQL минимальный корректный диапазон дат — от '1000-01-01' до '9999-12-31'. Необходимо учитывать эти ограничения при длительных сдвигах.
Функции перевода дат в числовые представления и обратно
Для работы с датами как с числами в SQL предусмотрены функции TO_DAYS() и FROM_DAYS(). TO_DAYS(дата) возвращает количество дней с начала отсчета, принятого как 0 год. Это целочисленное значение отражает позицию даты в шкале дней, что удобно для вычислений, сравнения и хранения.
Обратная функция FROM_DAYS(номер_дня) преобразует число дней в дату формата YYYY-MM-DD. Диапазон корректных дат ограничен внутренними пределами сервера. Значения вне диапазона приведут к NULL или ошибке.
SELECT TO_DAYS('2016-09-10'); // Возвращает: 736582
SELECT FROM_DAYS(736362); // Возвращает: 2016-02-03
Важно учитывать, что при переходе в григорианский календарь в 1582 году некоторые дни были пропущены. TO_DAYS() и FROM_DAYS() не учитывают эти пропуски, что искажает расчеты с датами до 1582 года. Следовательно, для исторических данных следует применять специальные библиотеки или внешние методы.
Функции TO_DAYS и FROM_DAYS не подходят для дат до 1582 года из-за разрыва календаря григорианского перехода.
Для представления времени как числовой величины в секундах применяются функции TIME_TO_SEC() и SEC_TO_TIME(). Первая принимает временной интервал в формате 'HH:MM:SS' и возвращает количество секунд, вторая — преобразует количество секунд обратно в формат времени.
SELECT TIME_TO_SEC('2:23:09'); // Результат: 8589
SELECT SEC_TO_TIME(8589); // Результат: 02:23:09
С помощью этих функций возможно выполнять арифметические операции над временными интервалами, например, суммируя длительности, или преобразовывать интервалы для хранения в числовом формате. Следует учитывать, что TIME_TO_SEC() работает корректно с интервалами до 838:59:59, поскольку MySQL ограничивает тип TIME этим диапазоном. В случае превышения RETURN-значения возможны ошибки или обрезка.
Типичные ошибки и ограничения при работе с датами в SQL
Одной из наиболее частых ошибок является неправильное использование типов интервала при вычислениях. Например, использование выражения без указания типа или с неверным форматом приводит к синтаксическим ошибкам или непредсказуемым результатам. Тип "YEAR_MONTH" требует формат "X-Y", а тип "MINUTE_SECOND" - формат "MM:SS".
При вычитании или прибавлении больших интервалов существует риск выхода за пределы допустимых значений даты в SQL. Например, попытка сдвинуть дату до 0000-00-00 или выше 9999-12-31 приводит к ошибке. Пользователь должен контролировать диапазон вводимых значений.
При работе с функциями TO_DAYS() и FROM_DAYS() важно помнить, что они используют упрощённый календарь без учета перехода на григорианский календарь. При работе с историческими датами до 1582 года результаты могут быть некорректными.
Другая ошибка — ожидание, что функции возвращают значения в определённом формате. Например, NOW() возвращает datetime, а CURDATE() — только дату. Сравнение datetime с date без приведения типов приводит к ошибкам фильтрации. Для сравнения либо нужно выполнять преобразование, либо использовать функции, явно обрезающие время.
Сравнение методов вычитания дат и преобразования времени
Методы арифметики с датами связаны по производительности и удобству использования. Выражения с оператором «+ INTERVAL» и функции DATE_ADD/DATE_SUB дают идентичный результат, но первый синтаксис воспринимается сложнее для новых пользователей. Функции ADDDATE и SUBDATE доступны с MySQL уже с версии 4.0, тогда как 'INTERVAL' появился с тех же версий. Разница в производительности очень незначительна, поэтому выбор определяется стилем кода.
Функции для преобразования дат в число дней и обратно не являются прямыми методами арифметики, но позволяют реализовать операции разницы между датами как разницу двух чисел, что ускоряет вычисления при больших объемах данных в индексах.
Сравнительная таблица методов с примерами:
Ниже приведена таблица с кратким описанием функций и их назначением.
| Функция/Выражение | Описание | Пример | Результат |
|---|---|---|---|
| CURDATE() | Возвращает текущую дату без времени | SELECT CURDATE(); | 2016-08-28 |
| NOW() | Текущая дата и время с точностью до секунды | SELECT NOW(); | 2016-08-28 19:29:54 |
| DATE_ADD() | Прибавляет интервал к дате | SELECT DATE_ADD('2016-09-10', INTERVAL 1 DAY); | 2016-09-11 |
| DATE_SUB() | Вычитает интервал из даты | SELECT DATE_SUB('2016-09-10', INTERVAL 1 MONTH); | 2016-08-10 |
| TO_DAYS() | Переводит дату в число дней | SELECT TO_DAYS('2016-09-10'); | 736582 |
| FROM_DAYS() | Преобразует число дней в дату | SELECT FROM_DAYS(736582); | 2016-09-10 |
| TIME_TO_SEC() | Преобразует временной интервал в секунды | SELECT TIME_TO_SEC('2:23:09'); | 8589 |
| SEC_TO_TIME() | Преобразует секунды в временной интервал | SELECT SEC_TO_TIME(8589); | 02:23:09 |
Матрица условий выбора функций и методов
При обработке дат и времени в SQL рекомендуется использовать следующие методы в зависимости от задачи и ограничений:
- Если требуется получить только дату без времени - использовать CURDATE() или CURRENT_DATE(). При этом результат строго в формате 'YYYY-MM-DD'. Ограничение - не содержит временной части.
- Для получения даты и времени с точностью до секунды применять NOW() или CURRENT_TIMESTAMP. Если момент вызова важен максимально точно, лучше использовать SYSDATE() - возвращает текущее значение в момент вызова, а не начала запроса.
- Для математических операций с датами и времени прибавление или вычитание интервалов делать через DATE_ADD(), DATE_SUB() или выражения с «INTERVAL». При этом важен правильный выбор типа интервала для корректной интерпретации выражения. Ошибочное использование типа приводит к неверным результатам.
- Для хранения или сравнения дат в числовом формате лучше использовать TO_DAYS() и FROM_DAYS(). Метод не применим к датам до 1582 года и ограничен диапазоном корректности даты в SQL.
- Для работы с временными интервалами внутри суток или с длительностью применить TIME_TO_SEC() и SEC_TO_TIME(). Максимальный диапазон — 838 часов 59 минут 59 секунд, что соответствует ограничению типа TIME в MySQL.
Новая версия SQL или движок СУБД могут влиять на поведение функций, поэтому при переносе скриптов между версиями рекомендуется проверять совместимость и корректность вычислений.