1с как в запросе проверить на пустую дату в запросе

Бесплатная консультация юриста

+7 (800) 302-87-29

Реклама jurik.ru

Работа с датами — одна из самых частых задач при разработке на платформе 1С:Предприятие 8. Особое внимание требует обработка «пустых» дат. В отличие от многих СУБД, где для отсутствия значения используется NULL, в 1С пустая дата имеет конкретное значение — 00:00:00. В этой статье подробно разберем, как правильно проверять дату на пустоту в тексте запроса, какие ошибки допускают новички и какие лучшие практики стоит применять.

Теория: Что такое пустая дата в 1С?

В системе 1С:Предприятие для типа данных Дата не существует отдельного состояния «не заполнено» (как NULL в SQL). Пустой датой считается значение:

  • Дата(1, 1, 1) — 1 января 0001 года 00:00:00.
  • В строковом представлении: '00010101' или '0001-01-01'.

Важно: Значение NULL в запросах 1С может появиться только как результат ЛЕВОГО СОЕДИНЕНИЯ (когда по условию соединения запись не найдена) или при обращении к недоступным реквизитам (например, реквизиты группы у элемента справочника). Сама по себе дата в базе данных не может быть равна NULL, если только это не результат соединения.

Основные способы проверки в тексте запроса

Сравнение с константой ДАТАВРЕМЯ (Рекомендуемый стандарт)

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

ВЫБРАТЬ
 Товары.Ссылка,
 Товары.ДатаПроизводства
ИЗ
 Справочник.Товары КАК Товары
ГДЕ
 Товары.ДатаПроизводства = ДАТАВРЕМЯ(1, 1, 1)

Плюсы: Явная семантика, не зависит от формата даты в настройках ИБ, понятно другим разработчикам.

Сравнение со строковым литералом (Устаревший, но встречающийся)

В старом коде часто встречается сравнение со строкой '00010101' или '0001-01-01'. Платформа автоматически приводит строку к типу Дата при сравнении.

ГДЕ
 Товары.ДатаПроизводства = '00010101'
 -- или
 Товары.ДатаПроизводства = '0001-01-01'

Минусы: Менее наглядно, может сбивать с толку (выглядит как строка), в редких случаях возможны проблемы с локализацией/форматом даты (хотя для ISO-формата обычно безопасно).

Использование параметра запроса (Best Practice для кода на встроенном языке)

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

// В модуле объекта / менеджера
Запрос = Новый Запрос;
Запрос.Текст = 
 "ВЫБРАТЬ Ссылка ИЗ Справочник.Товары ГДЕ ДатаПроизводства = &ПустаяДата";

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

Проверка на НЕ пустую дату

Для отбора заполненных дат используется оператор неравенства или отрицание.

// Вариант 1: Не равно
ГДЕ Товары.ДатаПроизводства <> ДАТАВРЕМЯ(1, 1, 1)

// Вариант 2: НЕ (Равно)
ГДЕ НЕ Товары.ДатаПроизводства = ДАТАВРЕМЯ(1, 1, 1)

Специфика LEFT JOIN: Пустая дата vs NULL

Это критически важный момент. При левом соединении, если запись в правой таблице не найдена, все поля этой таблицы (включая даты) становятся равны NULL, а не пустой дате.

Пример ошибки:
// ОШИБКА: Не найдет записи, где нет заказа, так как ДатаЗаказа будет NULL, а не 
ВЫБРАТЬ
 Товары.Ссылка,
 Заказы.ДатаЗаказа
ИЗ
 Справочник.Товары КАК Товары
 ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказПокупателя КАК Заказы
 ПО Товары.Ссылка = Заказы.Товар
ГДЕ
 Заказы.ДатаЗаказа = ДАТАВРЕМЯ(1, 1, 1) // Не сработает для NULL!

Правильный подход (операторы ЕСТЬ NULL / ЕСТЬ НЕ NULL):
ВЫБРАТЬ
 Товары.Ссылка,
 Заказы.ДатаЗаказа
ИЗ
 Справочник.Товары КАК Товары
 ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказПокупателя КАК Заказы
 ПО Товары.Ссылка = Заказы.Товар
ГДЕ
 Заказы.ДатаЗаказа ЕСТЬ NULL // Найти товары, у которых НЕТ заказа
 // ИЛИ
 Заказы.ДатаЗаказа ЕСТЬ НЕ NULL // Найти товары, у которых ЕСТЬ заказ (любая дата)

Резюме: Если поле даты может быть результатом ЛЕВОГО СОЕДИНЕНИЯ, проверяйте на ЕСТЬ NULL. Если это «родное» поле справочника/документа, которое просто не заполнил пользователь, проверяйте на ДАТАВРЕМЯ(1, 1, 1).

Функция ЗНАЧЕНИЕ в запросе

В запросах 1С существует функция ЗНАЧЕНИЕ, которая позволяет задать константу конкретного типа прямо в тексте запроса. Для пустой даты:

ГДЕ Товары.ДатаПроизводства = ЗНАЧЕНИЕ(Дата(1, 1, 1))

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

Проверка в модулях (Встроенный язык) — для контекста

Хотя статья про запросы, разработчики часто путают синтаксис запроса и синтаксис встроенного языка. В модулях (на сервере/клиенте) используются другие конструкции:

  • Если Дата = Дата(1, 1, 1) Тогда — классика.
  • Если ЗначениеЗаполнено(Дата) Тогда — современный стандарт. Функция возвращает Ложь для пустой даты , NULL, пустой строки, пустой ссылки и 0 для чисел. Рекомендуется к использованию везде, кроме текста запроса.
  • Если Не Дата = Дата(1, 1, 1) Тогда — проверка на заполненность.

Чек-лист: Типичные ошибки и как их избежать
  1. Ошибка: Писать ГДЕ Дата = NULL для обычных полей.

    Правильно: ГДЕ Дата = ДАТАВРЕМЯ(1, 1, 1). NULL в 1С — это отсутствие данных (результат LEFT JOIN), а не пустое значение скаляра.
  2. Ошибка: Использовать ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка) для дат.

    Правильно: ЗНАЧЕНИЕ с пустой ссылкой работает только для ссылочных типов. Для дат — только ДАТАВРЕМЯ(1,1,1).
  3. Ошибка: Сравнивать дату с пустой строкой ''.

    Результат: Ошибка несовместимости типов или неявное приведение, дающее неверный результат.
  4. Ошибка: Забывать про компоненту времени.

    Нюанс: ДАТАВРЕМЯ(1, 1, 1) создает дату с временем 00:00:00. Если в поле хранится 12:00:00 (теоретически возможно при ручном заполнении), сравнение с ДАТАВРЕМЯ(1,1,1) даст Ложь. Используйте ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0) для явности, хотя платформа обычно обнуляет время при записи «пустой» даты через интерфейс.

Пример комплексного запроса

Запрос, который выбирает номенклатуру, у которой не заполнена дата выпуска (пустая дата) ИЛИ нет данных о последней продаже (NULL после LEFT JOIN).

ВЫБРАТЬ
 Номенклатура.Ссылка КАК Номенклатура,
 Номенклатура.ДатаВыпуска КАК ДатаВыпуска,
 Продажи.ДатаПоследнейПродажи КАК ДатаПродажи,
 ВЫБОР
 КОГДА Номенклатура.ДатаВыпуска = ДАТАВРЕМЯ(1, 1, 1) ТОГДА "Дата выпуска не указана"
 КОГДА Продажи.ДатаПоследнейПродажи ЕСТЬ NULL ТОГДА "Никогда не продавалась"
 ИНАЧЕ "ОК"
 КОНЕЦ КАК Статус
ИЗ
 Справочник.Номенклатура КАК Номенклатура
 ЛЕВОЕ СОЕДИНЕНИЕ (
 ВЫБРАТЬ
 Номенклатура КАК Ном,
 МАКСИМУМ(Дата) КАК ДатаПоследнейПродажи
 ИЗ
 РегистрНакопления.Продажи
 СГРУППИРОВАТЬ ПО
 Номенклатура
 ) КАК Продажи
 ПО Номенклатура.Ссылка = Продажи.Ном
ГДЕ
 (Номенклатура.ДатаВыпуска = ДАТАВРЕМЯ(1, 1, 1))
 ИЛИ (Продажи.ДатаПоследнейПродажи ЕСТЬ NULL)

Резюме: Best Practices
Ситуация Правильная проверка в запросе
Поле даты справочника/документа не заполнено пользователем Поле = ДАТАВРЕМЯ(1, 1, 1)
Поле даты после ЛЕВОГО СОЕДИНЕНИЯ (запись не найдена) Поле ЕСТЬ NULL
Передача пустой даты из модуля в параметр запроса Запрос.УстановитьПараметр("Парам", Дата(1, 1, 1))
Проверка в коде модуля (не в тексте запроса) ЗначениеЗаполнено(Дата) — возвращает Истина/Ложь

Правильная работа с пустыми датами в запросах 1С — залог корректных отчетов и быстродействия. Главное правило: разделяйте понятия «Пустая дата » и «NULL (отсутствие данных после LEFT JOIN)». Используйте функцию ДАТАВРЕМЯ(1, 1, 1) для сравнения со скалярами и оператор ЕСТЬ NULL для анализа результатов внешних соединений. Всегда передавайте пустые даты в запросы через параметры, а в модулях применяйте универсальную функцию ЗначениеЗаполнено.