В языке запросов системы 1С:Предприятие работа с отсутствующими значениями является одной из самых частых задач при разработке отчетов и обработок данных. Разработчики часто сталкиваются с необходимостью получить список документов, у которых не заполнен контрагент, или найти номенклатуру без установленного родителя. Неправильная обработка таких ситуаций может привести к тому, что важная информация просто исчезнет из выборки или, наоборот, в отчет попадут лишние записи.
Основная сложность заключается в том, что в базе данных пустая ссылка и отсутствие значения (NULL) — это не совсем одно и то же с точки зрения логики выполнения запроса, хотя визуально в интерфейсе они могут выглядеть идентично. Понимание того, как платформа интерпретирует незаполненные поля, критически важно для написания корректного кода. В этой статье мы детально разберем все доступные методы фильтрации и сравнения.
Мы рассмотрим как стандартные операторы сравнения, так и специальные конструкции, предназначенные именно для работы с неопределенными значениями. Вы узнаете, почему простое сравнение с пустой строкой может не сработать для ссылочных типов данных и как использовать функцию ЕСТЬNULL для подмены значений на лету. Эти знания помогут вам избегать распространенных ошибок при построении сложных аналитических выборок.
Природа пустых значений в платформе 1С
Прежде чем переходить к синтаксису, необходимо четко понимать разницу между типами данных. В табличной части документа или в регистре поле может быть не заполнено. Для строковых типов это часто означает пустую строку "", однако для ссылочных типов (СправочникСсылка, ДокументСсылка) отсутствие значения представляется специальным системным значением NULL.
Когда вы создаете новый объект в базе данных и ничего не записываете в поле типа"СправочникСсылка", физически в ячейке таблицы SQL хранится маркер отсутствия данных. Это принципиально отличается от хранения ссылки на элемент с кодом"00000000000000000000000000000000". Пустая ссылка в контексте запроса 1С — это именно ситуация, когда значение не определено.
Важно отметить, что поведение при сравнении зависит от того, как сформирован запрос. Если вы пытаетесь сравнить поле с пустым значением, используя обычные операторы, результат может быть неоднозначным в зависимости от версии платформы и типа соединения. Поэтому для надежности следует использовать специализированные конструкции, предусмотренные разработчиками платформы.
⚠️ Внимание: В некоторых старых версиях платформы или при работе с внешними источниками данных через ODBC поведение NULL может отличаться от стандарта 1С. Всегда проверяйте логику отбора на тестовой базе перед внедрением в промышленную эксплуатацию.
Использование константы ЗНАЧЕНИЕ для отбора
Самый явный и понятный способ выбрать записи с пустыми ссылками — это явное сравнение поля с константой NULL. В языке запросов 1С для этого используется конструкция ЗНАЧЕНИЕ(Тип.ПустаяСсылка) или прямое указание типа в параметрах. Этот метод гарантирует, что вы отфильтруете именно те строки, где значение отсутствует.
Рассмотрим пример запроса, который выбирает все документы реализации, у которых не указан склад. Мы явно указываем, что поле Склад должно быть равно пустой ссылке на справочник складов.
ВЫБРАТЬ
РеализацияТоваровУслуг.Ссылка КАК Ссылка,
РеализацияТоваровУслуг.Склад
ИЗ
Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ГДЕ
РеализацияТоваровУслуг.Склад = ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка)
Такой подход является наиболее читаемым для других разработчиков, которые будут поддерживать ваш код в будущем. Он однозначно говорит о намерении автора запроса: нам нужны только записи без привязки к конкретному элементу справочника. Это особенно полезно в сложных запросах с множественными соединениями.
Однако стоит помнить, что использование функции ЗНАЧЕНИЕ внутри условия ГДЕ может в некоторых редких случаях (зависит от оптимизатора запросов СУБД) слегка влиять на производительность по сравнению с другими методами, хотя в современных версиях 1С эта разница часто нивелируется. Главное преимущество здесь — семантическая точность.
Если вы используете параметры в запросе, передавайте в них ПустуюСсылку соответствующего типа из кода 1С, а не строковое представление. Это обеспечит типобезопасность выборки.
Операторы ЕСТЬNULL и сравнение с ИСТИНА/ЛОЖЬ
Часто возникает задача не просто отобрать пустые значения, но и подменить их на что-то осмысленное для дальнейшей группировки или отображения. Для этого в языке запросов существует мощная функция ЕСТЬNULL. Она принимает два аргумента: проверяемое выражение и значение, которое нужно вернуть, если первое выражение равно NULL.
Функция ЕСТЬNULL работает как условный оператор. Если поле заполнено, она вернет его значение. Если поле пустое — вернет второй аргумент. Это позволяет избежать появления"дыр" в отчетах, где пустые ячейки могут сбивать с толку пользователя.
ВЫБРАТЬ
Номенклатура.Наименование,
ЕСТЬNULL(Номенклатура.Родитель, ЗНАЧЕНИЕ(Справочник.НоменклатурныеГруппы.ПустаяСсылка)) КАК Родитель
ИЗ
Справочник.Номенклатура КАК Номенклатура
Помимо подмены значений, эту функцию можно использовать и для фильтрации, хотя это менее распространено. Более интересным аспектом является работа с булевыми значениями. В 1С пустое значение булевого типа также трактуется как ЛОЖЬ в условиях отбора, если не указано иное. Но для явности лучше использовать сравнение с константой.
Использование ЕСТЬNULL особенно критично при объединении результатов нескольких запросов через ОБЪЕДИНИТЬ ВСЕ. Если в одной части выборки поле заполнено, а в другой нет, без приведения к общему виду (например, замене NULL на ПустуюСсылку) могут возникнуть ошибки типов или некорректная группировка данных.
☑️ Проверка логики работы с NULL
Сравнение пустых ссылок в соединениях таблиц
Одной из самых коварных областей являются соединения таблиц (ЛЕВОЕ СОЕДИНЕНИЕ, ВНУТРЕННЕЕ СОЕДИНЕНИЕ). Поведение системы при стыковке записей, где ключевое поле пустое, может привести к неожиданному уменьшению количества строк в выборке. В стандартном внутреннем соединении запись из левой таблицы не попадет в результат, если для нее не найдетсяющая запись в правой, включая случаи пустых ссылок.
Если вам нужно получить все документы, даже те, у которых не заполнен контрагент, использование ВНУТРЕННЕЕ СОЕДИНЕНИЕ с таблицей контрагентов автоматически отрежет такие документы. Правильным решением здесь будет использование ЛЕВОЕ СОЕДИНЕНИЕ.
| Тип соединения | Поведение с пустой ссылкой | Результат выборки |
|---|---|---|
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ | Требует наличия записи в правой таблице | Записи с пустой ссылкой исключаются |
| ЛЕВОЕ СОЕДИНЕНИЕ | Сохраняет запись из левой таблицы | Записи с пустой ссылкой сохраняются (поля правой таблицы NULL) |
| ПОЛНОЕ СОЕДИНЕНИЕ | Сохраняет все записи | Записи с пустой ссылкой сохраняются с обеих сторон |
При использовании левого соединения поля из правой таблицы для записей с пустой ссылкой будут равны NULL. Это необходимо учитывать при дальнейшем расчете итогов. Например, сумма по полю из правой таблицы для таких строк не будет посчитана, если не использовать ЕСТЬNULL для подмены нуля.
Иногда требуется отобрать именно те записи, которые не нашли пару в правой таблице при левом соединении. Для этого после соединения добавляют условие ГДЕ ПраваяТаблица.Ссылка ЕСТЬ NULL. Это классический паттерн для поиска"сиротских" записей или документов без проведения.
Оптимизация соединений с NULL
При большом объеме данных условие"ГДЕ... ЕСТЬ NULL" после левого соединения может выполняться медленно. В таких случаях рассмотрите возможность использования временных таблиц с предварительной фильтрацией.
Особенности работы с временными таблицами
При записи результатов запроса во временную таблицу (ПОМЕСТИТЬ) типы полей определяются автоматически на основе первой выборки. Если в первом запросе поле содержит только NULL значения, тип поля во временной таблице может быть определен некорректно для последующих операций, особенно при объединении с другими данными.
Чтобы избежать проблем с типизацией, рекомендуется явно приводить пустые значения к нужному типу при создании временной таблицы. Это делается с помощью все той же конструкции ЗНАЧЕНИЕ или функции приведения типа, если она доступна в конкретном контексте запроса.
Например, если вы формируете сводную таблицу, где в одной части есть данные о складе, а в другой их нет, убедитесь, что поле"Склад" во всех частях объединения имеет тип СправочникСсылка.Склады, а не строку или неопределенный тип.
ВЫБРАТЬ
Номенклатура.Ссылка,
ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка) КАК Склад
ПОМЕСТИТЬ
ВТ_НоменклатураБезСклада
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
...
Такая явная типизация защищает ваш код от ошибок выполнения вида"Неверный тип значения" при попытке соединить эту временную таблицу с другими данными, где поле"Склад" точно заполнено ссылками. Это правило хорошего тона в программировании на 1С.
Частые ошибки и методы отладки
Самая распространенная ошибка новичков — попытка сравнить ссылочное поле с пустой строкой "". В языке запросов 1С это сравнение всегда вернет ЛОЖЬ, так как типы несовместимы, и запись не будет отобрана. Пустая строка и пустая ссылка — это разные сущности в памяти базы данных.
Еще одна ошибка заключается в игнорировании регистранезависимости некоторых сравнений или особенностей collation базы данных, хотя для NULL и пустых ссылок это менее актуально. Главное — помнить о типовой безопасности.
Для отладки таких запросов удобно использовать консоль запросов. Выполните запрос без условия ГДЕ, посмотрите на результат, а затем постепенно добавляйте фильтры. Если количество строк обнуляется там, где не должно, проверьте условия сравнения на наличие NULL.
⚠️ Внимание: При использовании динамических списков в формах 1С условия отбора могут автоматически трансформироваться платформой. Убедитесь, что ваше условие"Пустая ссылка" корректно передается в СКД (Систему Компоновки Данных).
Практические рекомендации по оптимизации
Хотя проверка на NULL является необходимой операцией, на огромных массивах данных (миллионы записей в регистрах накопления) она может требовать дополнительных ресурсов процессора. Индексы в SQL обычно хорошо обрабатывают NULL значения, но специфика 1С может вносить свои коррективы.
Старайтесь избегать конструкций, где проверка на пустоту происходит внутри вычисляемых полей в условии ГДЕ, если это возможно. Лучше вынести такую логику в отдельные этапы запроса или использовать временные таблицы для предварительной фильтрации.
Если вы работаете с составными типами (например, поле может быть ссылкой на Справочник или на Документ), проверка на пустую ссылку усложняется. В этом случае необходимо проверять тип значения или использовать универсальную пустую ссылку, если контекст позволяет. Однако в современных версиях 1С предпочтительно избегать составных типов в ключевых полях отбора.
Использование явной константы ЗНАЧЕНИЕ(Тип.ПустаяСсылка) является самым надежным и производительным способом фильтрации записей с незаполненными ссылками в 1С.
В чем разница между пустой строкой и пустой ссылкой в 1С?
Пустая строка — это значение строкового типа длиной 0 символов. Пустая ссылка — это специальное значение для ссылочных типов, означающее отсутствие связи с объектом базы данных. Сравнивать их напрямую нельзя.
Как проверить, что поле не заполнено, используя ЕСТЬNULL?
Функция ЕСТЬNULL возвращает второй аргумент, если первый равен NULL. Для проверки можно использовать конструкцию: ЕСЛИ ЕСТЬNULL(Поле, ЛОЖЬ) = ЛОЖЬ, но проще сравнивать поле напрямую с ЗНАЧЕНИЕ(Тип.ПустаяСсылка).
Почему внутреннее соединение отрезает записи с пустыми ссылками?
Внутреннее соединение требует наличия matching записи в обеих таблицах. Пустая ссылка не может быть сопоставлена с конкретной записью в правой таблице, поэтому условие соединения не выполняется, и строка исключается из результата.
Можно ли использовать оператор IS NULL в запросах 1С?
В нативном языке запросов 1С оператор SQL"IS NULL" не используется напрямую в тексте запроса. Вместо него применяется сравнение с константой ЗНАЧЕНИЕ(...) или логика платформы, которая транслирует это в соответствующий SQL-код при генерации запроса к СУБД.