Пустая дата в запросе 1С: способы сравнения, типичные ошибки и практические примеры

Разбираем, как корректно указать и сравнить пустую дату в запросах 1С:Предприятие 8.3. Функция ДАТАВРЕМЯ, параметры запроса, отличия от NULL, частые ошибки и оптимизация.

Что такое пустая дата в 1С и почему это не ноль

В платформе 1С:Предприятие 8 понятие «пустая дата» отличается от привычного нуля или пустой строки. Переменная типа «Дата» всегда содержит конкретное значение, даже если пользователь не заполнял поле. Система автоматически подставляет минимально возможную дату, которая в большинстве конфигураций соответствует 1 января 0001 года по григорианскому календарю. Это значение часто называют «пустой датой», хотя технически оно не является отсутствием данных.

В отличие от SQL, где поле может быть NULL, в таблицах 1С для реквизитов с типом «Дата» обычно хранится именно минимальная дата. Поэтому сравнение с нулём или пустой строкой не работает: язык запросов строго типизирован, и попытка сравнить дату с числом приведёт к ошибке выполнения или всегда будет возвращать ложь.

Понимание этого принципа критично при написании запросов к документам, регистрам сведений и регистрам накопления. Например, если в регистре сведений хранится дата отправки письма, и она не заполнена, в базе будет лежать 01.01.0001. Чтобы выбрать такие записи, нужно явно указать это значение в условии отбора.

Функция ДАТАВРЕМЯ: основной способ задания пустой даты

Самый надёжный и рекомендуемый способ указать пустую дату в тексте запроса — использовать встроенную функцию ДАТАВРЕМЯ(). Она позволяет сконструировать дату, передав год, месяц, день, час, минуты и секунды. Для пустой даты обычно используют ДАТАВРЕМЯ(1, 1, 1) или полный вариант ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0).

Пример условия отбора:

ВЫБРАТЬ
    Документ.Ссылка,
    Документ.Дата
ИЗ
    Документ.РеализацияТоваровУслуг КАК Документ
ГДЕ
    Документ.Дата = ДАТАВРЕМЯ(1, 1, 1)

Такой подход делает код читаемым и понятным для других разработчиков. Вместо «магической» строки '00010101' вы явно показываете намерение выбрать записи с минимальной датой. Кроме того, функция работает одинаково на всех поддерживаемых СУБД, что важно при переносе базы с MS SQL на PostgreSQL или обратно.

Если нужно указать непустую дату, синтаксис аналогичен: ДАТАВРЕМЯ(2025, 12, 31, 23, 59, 59). Главное — не забывать, что в некоторых конфигурациях минимальной датой может считаться 01.01.1900 или 01.01.2000. Поэтому перед использованием проверьте, какое значение реально хранится в вашей базе, особенно если вы работаете с унаследованными данными.

Передача пустой даты через параметр запроса

Альтернативный и часто более гибкий способ — передать пустую дату как параметр запроса. Это позволяет не хардкодить значение в тексте запроса и упрощает его повторное использование. В коде 1С параметр устанавливается с помощью метода УстановитьПараметр().

Пример:

Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|   ПланОтправкиЭлектронныхПисем.Ссылка
|ИЗ
|   РегистрСведений.ПланОтправкиЭлектронныхПисем КАК ПланОтправкиЭлектронныхПисем
|ГДЕ
|   ПланОтправкиЭлектронныхПисем.ПисьмоОтправлено = &ПустаяДата";

Запрос.УстановитьПараметр("ПустаяДата", Дата(1, 1, 1));
Результат = Запрос.Выполнить();

Использование параметров защищает от SQL-инъекций (хотя в 1С это менее актуально) и делает код более гибким. Если логика изменится и потребуется искать записи с другой датой, достаточно изменить значение параметра, не редактируя текст запроса.

Особенно полезно передавать параметр, когда минимальная дата может различаться в зависимости от версии платформы или конфигурации. Вместо жёстко заданного Дата(1,1,1) можно использовать глобальную функцию МинимальнаяДата(), которая возвращает актуальное значение для текущей системы. Это снижает риск ошибок при обновлении или переносе базы.

Отличия от NULL и НЕОПРЕДЕЛЕНО в запросах

В языке запросов 1С существует специальное значение НЕОПРЕДЕЛЕНО, которое соответствует SQL NULL. Однако для полей типа «Дата» в документах и большинстве регистров оно не применяется: вместо NULL хранится минимальная дата. Поэтому проверка ПолеДаты ЕСТЬ NULL часто не возвращает ожидаемых записей.

Ситуации, когда НЕОПРЕДЕЛЕНО может быть уместно, возникают при работе с виртуальными таблицами или реквизитами, у которых снята галочка «Заполнять нулем» в свойствах метаданных. В таких случаях поле действительно может содержать NULL, и тогда условие ЕСТЬ NULL сработает корректно.

Важно не путать эти понятия. Если вы видите в интерфейсе пустое поле даты, это почти всегда означает, что в базе хранится минимальная дата, а не NULL. Поэтому для типовых конфигураций используйте сравнение с ДАТАВРЕМЯ(1,1,1) или параметром, а не проверку на НЕОПРЕДЕЛЕНО.

Если вы разрабатываете собственную конфигурацию и хотите разрешить настоящую пустоту в поле даты, необходимо отключить автоматическое заполнение нулём. Только после этого проверка на НЕОПРЕДЕЛЕНО станет осмысленной.

Особенности работы с датами в 1С 7.7 и при переносе данных

Хотя платформа 1С 7.7 считается устаревшей, некоторые компании до сих пор её используют. Подход к пустым датам там отличается: часто применялись строковые представления или числовые эпохи. В запросах 7.7 пустая дата могла обозначаться как пустая строка или минимальная дата, но синтаксис функции ДатаВремя мог отличаться в зависимости от диалекта.

При переносе данных из 7.7 в 8.0 все пустые даты автоматически преобразуются в 01.01.1900. Это поведение нельзя изменить стандартными средствами конвертера, поэтому после миграции требуется очистка данных специальными обработками. Если вы работаете с унаследованной базой, проверьте, какая минимальная дата фактически используется, и адаптируйте запросы соответствующим образом.

Для платформы 8.3 рекомендуется всегда использовать ДАТАВРЕМЯ(1,1,1) или параметр с МинимальнаяДата(), чтобы избежать проблем при обновлении или переносе. Хардкод строк вида '01.01.1900' считается плохой практикой, так как он может не совпадать с реальным значением в конкретной базе.

Типичные ошибки при сравнении с пустой датой

Одна из самых частых ошибок — несовпадение времени. Дата 01.01.0001 00:00:00 не равна дате 01.01.0001 12:30:00. Если в базе поле заполнено с ненулевым временем, простое равенство не сработает. В таких случаях нужно использовать диапазон дат или функцию НАЧАЛОДНЯ() для приведения к общему виду перед сравнением.

Другая распространённая ошибка — попытка сравнить дату со строкой "0" или числом 0. Система строго типизирована, и такое сравнение вызовет ошибку выполнения или всегда вернёт ложь. Всегда приводите типы данных к единому виду.

Также разработчики иногда забывают, что в разных конфигурациях минимальная дата может отличаться. Например, в некоторых базах пустой датой считается 01.01.1900, а в других — 01.01.0001. Если запрос с ДАТАВРЕМЯ(1900,1,1) не возвращает ожидаемых записей, проверьте фактическое значение через консоль запросов.

Наконец, не стоит использовать «магические числа» в тексте запроса без комментариев. Это затрудняет поддержку кода и может привести к ошибкам при изменении логики.

Оптимизация запросов с фильтрацией по датам

Фильтрация по датам — одна из самых частых операций в запросах 1С, и её производительность напрямую влияет на скорость работы отчётов и обработок. Чтобы избежать замедлений, следуйте нескольким правилам.

Во-первых, всегда используйте индексируемые поля в условиях отбора. Если поле даты входит в состав индекса, СУБД сможет быстро найти нужные записи. В противном случае выполняется полное сканирование таблицы, что критично для больших объёмов данных.

Во-вторых, избегайте функций над полем даты в условиях, например НАЧАЛОДНЯ(Дата) = &НачалоДня. Такие выражения препятствуют использованию индекса. Вместо этого передавайте параметры с уже вычисленными границами диапазона.

В-третьих, если нужно отобрать записи с пустой датой, старайтесь использовать точное сравнение с ДАТАВРЕМЯ(1,1,1) или параметром, а не диапазон МЕЖДУ. Это позволит СУБД применить индекс более эффективно.

Наконец, для виртуальных таблиц регистров накопления и бухгалтерии используйте условия по периоду, чтобы ограничить выборку. Это снижает нагрузку на сервер и ускоряет выполнение запроса.

Практические примеры: отбор документов и регистров

Рассмотрим несколько типовых сценариев, где требуется работа с пустой датой.

Пример 1: Найти документы с незаполненной датой отгрузки

ВЫБРАТЬ
    Документ.Ссылка
ИЗ
    Документ.РеализацияТоваровУслуг КАК Документ
ГДЕ
    Документ.ДатаОтгрузки = ДАТАВРЕМЯ(1, 1, 1)

Пример 2: Выбрать записи регистра сведений, где дата отправки не задана

ВЫБРАТЬ
    Регистр.Ссылка
ИЗ
    РегистрСведений.ПланОтправкиЭлектронныхПисем КАК Регистр
ГДЕ
    Регистр.ДатаОтправки = &ПустаяДата

В коде параметр устанавливается как Дата(1,1,1) или МинимальнаяДата().

Пример 3: Исключить записи с пустой датой из отчёта

ВЫБРАТЬ
    Документ.Ссылка,
    Документ.Дата
ИЗ
    Документ.ЗаказКлиента КАК Документ
ГДЕ
    Документ.ДатаОплаты > ДАТАВРЕМЯ(1, 1, 1)

Такие запросы часто используются в отчётах по просроченным заказам или неотправленным письмам. Важно помнить, что при сравнении с пустой датой нужно учитывать возможное наличие времени в поле.

Рекомендации по стилю кода и поддержке

Чтобы код был понятным и легко поддерживаемым, придерживайтесь нескольких простых правил.

Используйте параметры запроса вместо хардкода дат. Это упрощает изменение логики и снижает риск ошибок. Если параметр не нужен, применяйте ДАТАВРЕМЯ(1,1,1) — это явно указывает на намерение.

Избегайте строковых литералов вида '00010101' — они менее читаемы и могут вызвать путаницу. Вместо этого используйте функцию Дата(1,1,1) в коде или ДАТАВРЕМЯ(1,1,1) в запросе.

Добавляйте комментарии к сложным условиям, особенно если минимальная дата в вашей конфигурации отличается от стандартной. Это поможет другим разработчикам быстро разобраться в логике.

Проверяйте запросы в консоли запросов перед внедрением. Это позволяет увидеть фактическое значение пустой даты в вашей базе и убедиться, что условие отбора работает корректно.

Наконец, при переносе данных между базами или обновлении платформы перепроверяйте запросы с датами, так как минимальная дата может измениться.

Вопросы и ответы

Почему сравнение даты с нулём не работает в запросе 1С?

В 1С тип «Дата» — это структурированное значение, а не число. Сравнение с нулём или пустой строкой приводит к ошибке типизации или всегда возвращает ложь. Вместо этого нужно использовать ДАТАВРЕМЯ(1,1,1) или параметр с минимальной датой.

Какая дата считается пустой в 1С:Предприятие 8.3?

По умолчанию пустой датой считается 1 января 0001 года. Однако в некоторых конфигурациях или после переноса данных из 7.7 минимальной датой может быть 01.01.1900 или 01.01.2000. Всегда проверяйте фактическое значение в вашей базе.

Можно ли использовать НЕОПРЕДЕЛЕНО для проверки пустой даты?

В большинстве типовых конфигураций поля дат не содержат NULL — вместо него хранится минимальная дата. Поэтому проверка ЕСТЬ NULL не сработает. Используйте сравнение с ДАТАВРЕМЯ(1,1,1) или параметром. НЕОПРЕДЕЛЕНО уместно только если в метаданных отключено заполнение нулём.

Что делать, если запрос с пустой датой не возвращает записи?

Проверьте, какое значение реально хранится в поле. Возможно, дата содержит ненулевое время, и простое равенство не срабатывает. Используйте диапазон дат или функцию НАЧАЛОДНЯ() для приведения к общему виду. Также убедитесь, что минимальная дата в вашей конфигурации соответствует ожидаемой.

Как передать пустую дату в параметр запроса?

В коде 1С используйте метод УстановитьПараметр("ИмяПараметра", Дата(1,1,1)) или МинимальнаяДата(). В тексте запроса обратитесь к параметру через амперсанд, например &ПустаяДата.

Чем отличается ДАТАВРЕМЯ(1,1,1) от ДАТАВРЕМЯ(1900,1,1)?

ДАТАВРЕМЯ(1,1,1) возвращает 1 января 0001 года — стандартную пустую дату в 1С 8.3. ДАТАВРЕМЯ(1900,1,1) — это 1 января 1900 года, которая может использоваться в унаследованных базах. Выбор зависит от того, какое значение фактически хранится в вашей системе.

Как оптимизировать запрос с фильтром по пустой дате?

Используйте точное сравнение с ДАТАВРЕМЯ(1,1,1) или параметром, избегайте функций над полем даты в условиях. Убедитесь, что поле даты индексировано. Для регистров ограничивайте выборку периодом через виртуальные таблицы.