Работа с пустыми значениями — одна из самых частых задач при написании запросов в 1С:Предприятие 8.3. Неправильная проверка на пустоту приводит к ошибкам в отчетах, пропуску записей или некорректным соединениям таблиц. В этой статье подробно разберем, как проверять пустые ссылки, строки, даты, числа и параметры запроса, а также рассмотрим нюансы работы с NULL и функцией ЕСТЬNULL.
Основные типы «пустоты» в 1С
В языке запросов 1С существует несколько разновидностей пустых значений, и для каждого типа используется свой синтаксис проверки:
- Пустая ссылка — значение ссылочного типа (Справочник, Документ, ПланОбмена и т.д.), не указывающее на объект.
- Пустая строка — строка нулевой длины
"". - Пустая дата, значение
ДАТАВРЕМЯ(1, 1, 1). - Ноль — для числовых типов.
- NULL, специальное значение, означающее «отсутствие значения» (часто возникает при левых соединениях).
- Неопределено, значение типа
Неопределено(в запросах встречается редко, чаще в коде модулей).
Проверка пустой ссылки в запросе
Это самая частая операция. Есть два основных способа сделать это в тексте запроса.
Способ 1: Функция ЗНАЧЕНИЕ (Рекомендуемый)
Самый читаемый и универсальный способ — использовать функцию ЗНАЧЕНИЕ с вызовом метода ПустаяСсылка у менеджера соответствующего метаданных.
ВЫБРАТЬ
Товары.Ссылка
ИЗ
Справочник.Номенклатура КАК Товары
ГДЕ
Товары.Родитель = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
Важно: Тип пустой ссылки должен строго соответствовать типу проверяемого поля. Если поле Родитель имеет тип СправочникСсылка.Номенклатура, то и пустая ссылка должна быть именно этого типа.
Способ 2: Передача через параметр запроса
Часто удобнее подготовить значение в коде и передать его как параметр. Это полезно, если запрос формируется динамически или тип ссылки неизвестен заранее.
// Код на встроенном языке
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура ГДЕ Родитель = &ПустойРодитель";
ПустаяСсылка = Справочники.Номенклатура.ПустаяСсылка;
Запрос.УстановитьПараметр("ПустойРодитель", ПустаяСсылка);
Результат = Запрос.Выполнить;
Способ 3: Сравнение с NULL (Только для LEFT JOIN)
Если вы делаете левое соединение и хотите отобрать записи, где связи нет, проверяйте поле связанной таблицы на ЕСТЬ NULL.
ВЫБРАТЬ
Заказы.Ссылка
ИЗ
Документ.ЗаказПокупателя КАК Заказы
ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК Реализации
ПО Заказы.Ссылка = Реализации.ЗаказПокупателя
ГДЕ
Реализации.Ссылка ЕСТЬ NULL
Здесь проверка Реализации.Ссылка = ЗНАЧЕНИЕ(...ПустаяСсылка) не сработает, так как при отсутствии связи поле содержит именно NULL, а не пустую ссылку.
Проверка пустой строки
Для строковых полей пустое значение — это строка нулевой длины. В языке запросов она обозначается двумя одинарными кавычками без пробела: '';
ВЫБРАТЬ
Контрагенты.Наименование
ИЗ
Справочник.Контрагенты КАК Контрагенты
ГДЕ
Контрагенты.Наименование = ''
// Или так:
// Контрагенты.Наименование <> ''
Нюанс: В некоторых версиях платформы/СУБД сравнение с пустой строкой может не сработать, если в поле лежит NULL. Надежнее использовать комбинацию:
ГДЕ
(Контрагенты.Наименование = '' ИЛИ Контрагенты.Наименование ЕСТЬ NULL)
Проверка пустой даты
Пустая дата в 1С — это 00:00:00. В запросе задается через литерал ДАТАВРЕМЯ.
ВЫБРАТЬ
Договоры.Ссылка
ИЗ
Справочник.Договоры КАК Договоры
ГДЕ
Договоры.ДатаОкончания = ДАТАВРЕМЯ(1, 1, 1)
Работа с параметрами запроса: проверка на заполненность
Частая задача: сделать условие в запросе опциональным. Если параметр передан — фильтруем, если не передан (пустой) — игнорируем фильтр.
Вариант А: Конструкция РАЗНОСТЬ (или CASE) в условии ГДЕ
ВЫБРАТЬ
Товары.Ссылка
ИЗ
Справочник.Номенклатура КАК Товары
ГДЕ
(Товары.ВидНоменклатуры = &ВидНоменклатуры ИЛИ &ВидНоменклатуры = ЗНАЧЕНИЕ(Справочник.ВидыНоменклатуры.ПустаяСсылка))
Здесь мы явно проверяем, равен ли параметр пустой ссылке его типа.
Вариант Б: Динамическое формирование текста запроса (Производительнее)
Если параметров много, лучше не загромождать запрос проверками ИЛИ Параметр = Пусто, а добавлять условие в текст запроса только при необходимости.
ТекстЗапроса = "ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура";
Условия = Новый Массив;
Если Не Параметры.ВидНоменклатуры = Справочники.ВидыНоменклатуры.ПустаяСсылка Тогда
Условия.Добавить("ВидНоменклатуры = &ВидНоменклатуры");
КонецЕсли;
Если Не Параметры.Группа = Справочники.Номенклатура.ПустаяСсылка Тогда
Условия.Добавить("Родитель = &Группа");
КонецЕсли;
Если Условия.Количество > 0 Тогда
ТекстЗапроса = ТекстЗапроса + " ГДЕ " + СтрСоединить(Условия, " И ");
КонецЕсли;
Запрос.Текст = ТекстЗапроса;
// Устанавливаем только нужные параметры
Если Не Параметры.ВидНоменклатуры = Справочники.ВидыНоменклатуры.ПустаяСсылка Тогда
Запрос.УстановитьПараметр("ВидНоменклатуры", Параметры.ВидНоменклатуры);
КонецЕсли;
// ...
Функция ЕСТЬNULL (ISNULL) — замена NULL на значение
Функция ЕСТЬNULL(Поле, Замена) возвращает Замена, если Поле равно NULL, иначе возвращает значение поля. Это критически важно при левых соединениях и агрегации.
ВЫБРАТЬ
Товары.Наименование,
ЕСТЬNULL(Товары.Артикул, "Без артикула") КАК Артикул
ИЗ
Справочник.Номенклатура КАК Товары
Пример 2: Использование в условиях отбора
Частая ошибка: ГДЕ Товары.Артикул = "" не найдет записи, где Артикул = NULL. Правильно:
ГДЕ
ЕСТЬNULL(Товары.Артикул, "") = ""
Пример 3: Суммирование с защитой от NULL
При суммировании полей, которые могут быть NULL (нет движений в регистре), результат суммы станет NULL.
ВЫБРАТЬ
Товары.Ссылка,
СУММА(ЕСТЬNULL(Остатки.Количество, 0)) КАК Остаток
ИЗ
Справочник.Номенклатура КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиТоваров КАК Остатки
ПО Товары.Ссылка = Остатки.Номенклатура
СГРУППИРОВАТЬ ПО
Товары.Ссылка
Проверка параметров в СКД (Система компоновки данных)
В СКД параметры проверяются в настройках схемы компоновки или в коде обработки параметров.
- Автоотбор по параметру: Если в схеме компоновки параметр не задан пользователем, он получает значение
Неопределено(или пустую ссылку/дату/строку в зависимости от типа). Условие автоотбора срабатывает только если параметр не равен значению «пусто» для своего типа. - Ручная проверка в процедуре ПриКомпоновкеРезультата:
Процедура ПриКомпоновкеРезультата(ДокументРезультата, ДанныеРасшифровки, СтандартнаяОбработка) Если Не ЗначениеЗаполнено(ПараметрыДанных.Контрагент) Тогда // Параметр не выбран пользователем // Можно вывести сообщение или изменить запрос КонецЕсли; КонецПроцедуры
Типичные ошибки и лучшие практики
| Ошибка | Почему это плохо | Как правильно |
|---|---|---|
ГДЕ Поле = NULL | В SQL и языке запросов 1С NULL = NULL` — это `NULL` (не Истина). Сравнение не сработает. | Использовать ГДЕ Поле ЕСТЬ NULL. |
Сравнение ссылки с пустой строкой ГДЕ Ссылка = "" | Ошибка типов: нельзя сравнивать ссылочный тип со строковым. | ГДЕ Ссылка = ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка). |
| Игнорирование NULL при LEFT JOIN | Поле связанной таблицы будет NULL, а не ПустаяСсылка. Условие Поле = ПустаяСсылка отсеет эти строки. | Проверять Поле ЕСТЬ NULL или использовать ЕСТЬNULL(Поле, ПустаяСсылка) = ПустаяСсылка. |
Передача в параметр запроса значения Неопределено | Запрос упадет с ошибкой несоответствия типов, если параметр используется в сравнении. | Всегда передавать типизированное пустое значение: Справочники.Имя.ПустаяСсылка, "", ДАТАВРЕМЯ(1,1,1), 0. |
Шпаргалка: Синтаксис пустых значений в тексте запроса
| Тип данных | Литерал в тексте запроса | Функция получения в коде 1С |
| :--- | :--- | :--- |
| Ссылка | `ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка)` | `Справочники.Имя.ПустаяСсылка` |
| Строка | `''` (две одинарные кавычки) | `""` |
| Дата | `ДАТАВРЕМЯ(1, 1, 1)` | `'00010101'` или `Дата(1,1,1)` |
| Число | `0` | `0` |
| Перечисление | `ЗНАЧЕНИЕ(Перечисление.Имя.Значение)` | `Перечисления.Имя.Значение` (пустого перечисления не существует, есть конкретное значение) |
| NULL | Ключевое слово `NULL` (только в условиях `ЕСТЬ NULL`) | Не существует в языке 1С (только в запросах) |
Правильная работа с пустыми значениями — залог быстрых и корректных запросов. Главные правила:
- Используйте ЗНАЧЕНИЕ(Метаданные.ПустаяСсылка) для ссылок прямо в тексте запроса.
- Передавайте в параметры запроса типизированные пустые значения, а не `Неопределено`.
- При LEFT JOIN всегда помните про NULL и используйте ЕСТЬNULL или условие ЕСТЬ NULL.
- Для опциональных фильтров предпочитайте динамическое построение текста запроса вместо конструкций `ИЛИ Параметр = Пусто`, это дает лучший план выполнения на СУБД.
Соблюдение этих принципов избавит вас от часов отладки «почему не выбираются записи» и «почему сумма NULL».