Как в запросе 1С отфильтровать пустые ГУИДы при использовании функции УНИКАЛЬНЫЙИДЕНТИФИКАТОР

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

С выходом платформы «1С:Предприятие» версии 8.3.24 разработчики получили долгожданный инструмент — встроенную функцию языка запросов УНИКАЛЬНЫЙИДЕНТИФИКАТОР(). До этого момента получение строкового или типизированного идентификатора ссылки непосредственно в запросе было нетривиальной задачей, требовавшей либо постобработки в коде, либо сложных манипуляций с двоичными данными на уровне СУБД. Однако новая функция принесла и новые вопросы, в частности: как правильно сравнивать полученный результат с «пустым» идентификатором?

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

Почему не работает сравнение со строкой

Рассмотрим типичную ошибку начинающего разработчика. Проанализируем ситуацию: функция УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Ссылка) возвращает объект специального типа УникальныйИдентификатор, а не обычную строку. Поэтому попытка выполнить сравнение следующим образом приведет к ошибке или неверному результату:


// ТАК РАБОТАТЬ НЕ БУДЕТ
ГДЕ УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Т.Ссылка) = "00000000-0000-0000-0000-000000000000"

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

Способ №1: Использование функции ЗНАЧЕНИЕ() в запросе

Самый быстрый и лаконичный способ отфильтровать пустые значения прямо в тексте запроса — это использование предопределенного значения пустой ссылки. Выясним причину, почему это работает: функция УНИКАЛЬНЫЙИДЕНТИФИКАТОР() может принимать в качестве аргумента пустую ссылку любого типа, возвращая при этом стандартный пустой ГУИД (все нули).

Рассмотрим пример правильного написания условия:


ВЫБРАТЬ
    Продажи.Ссылка,
    УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Продажи.Ссылка) КАК ГУИД
ИЗ
    Документ.РеализацияТоваровУслуг КАК Продажи
ГДЕ
    УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Продажи.Ссылка) <> УНИКАЛЬНЫЙИДЕНТИФИКАТОР(ЗНАЧЕНИЕ(Документ.РеализацияТоваровУслуг.ПустаяСсылка))

В данном примере мы сравниваем результат вычисления функции от текущей ссылки с результатом вычисления функции от пустой ссылки. Это «чистый» способ, не требующий передачи дополнительных параметров извне, напоминающий формирование текста запроса для работы с иерархией.

Способ №2: Передача пустого ГУИДа через параметр

Многие разработчики придерживаются мнения, что вычисление констант лучше выносить за пределы текста запроса для повышения читаемости и «чистоты» кода. Проанализируем этот подход. Мы можем заранее подготовить пустой идентификатор в коде 1С и передать его в запрос.

Пример кода на встроенном языке (для ускорения написания можно использовать ИИ-помощника для генерации каркаса кода):


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Номенклатура.Ссылка
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |	УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Номенклатура.Ссылка) <> &ПустойУИД";

// Создаем пустой идентификатор
Запрос.УстановитьПараметр("ПустойУИД", Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000"));
Результат = Запрос.Выполнить();

Этот метод считается более универсальным, так как он позволяет избежать привязки к конкретному типу метаданных (нам не нужно указывать Документ.Реализация...ПустаяСсылка), к тому же удобно использовать список GUID объектов и готовый код для получения ссылок.

Важный нюанс: Работа с NULL при левых соединениях

Посмотрим на ситуацию глубже. Часто функция УНИКАЛЬНЫЙИДЕНТИФИКАТОР() используется для полей, полученных в результате ЛЕВОЕ СОЕДИНЕНИЕ. Если для записи из левой таблицы не нашлось соответствия в правой, поле ссылки примет значение NULL.

Важно: в этом случае функция вернет NULL, а не пустой ГУИД из нулей! Следовательно, обычная проверка на неравенство пустому ГУИДу может пропустить такие записи. Проанализируем правильную конструкцию фильтра в таких случаях:


ГДЕ
    (УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Т.Ссылка) <> &ПустойУИД 
     ИЛИ УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Т.Ссылка) ЕСТЬ НЕ NULL)

Или, что более правильно с точки зрения логики запроса, предварительно обрабатывать NULL функцией ЕСТЬNULL, но помните, что ЕСТЬNULL(Ссылка, ПустаяСсылка) вернет ссылку, которую потом уже можно превратить в идентификатор.

Производительность и индексация (SARGability)

Рассмотрим вопрос производительности, который часто вызывает споры. Когда мы пишем ГДЕ УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Ссылка) <> ..., мы заставляем СУБД вычислять функцию для каждой строки таблицы. В терминах баз данных это делает условие «не-SARGable» (Search Argumentable).

Что это означает на практике?

  1. Сканирование вместо поиска: СУБД, скорее всего, не сможет использовать индекс по полю _IDRRef (ссылка), так как значение обернуто в функцию. Вместо быстрого поиска по индексу (Index Seek) будет выполнено полное сканирование таблицы или индекса (Index Scan), что на больших объемах данных (миллионы строк) приведет к существенным задержкам.
  2. Трансляция в SQL: 1С транслирует эту функцию в специфические команды. Для MS SQL это приведение типов (Cast/Convert), а для PostgreSQL — сложная цепочка преобразований байтового массива в UUID.

Рекомендация: Если ваша задача — просто отфильтровать пустые ссылки, всегда делайте это напрямую по полю ссылки, не используя функцию идентификатора в секции ГДЕ.

Сравним два варианта:

Плохо (медленно):

ГДЕ УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Т.Ссылка) <> &ПустойУИД

Хорошо (быстро):

ГДЕ Т.Ссылка <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)

Функцию УНИКАЛЬНЫЙИДЕНТИФИКАТОР() лучше оставить для секции ВЫБРАТЬ, когда вам нужно именно отобразить или выгрузить строковый ID во внешнюю систему.

Особенности различных СУБД

Выясним, как платформа 1С обеспечивает работу этой функции на разных движках БД. Несмотря на то, что для разработчика код выглядит одинаково, итоговый SQL-запрос будет отличаться:

Таким образом, использование ЗНАЧЕНИЕ() или параметра одинаково эффективно интерпретируется платформой перед отправкой запроса в СУБД. Выбор между ними — это вопрос ваших стандартов разработки и предпочтений по чистоте кода.

Резюме

Для фильтрации пустых ГУИДов в запросах 1С:

  1. Используйте УНИКАЛЬНЫЙИДЕНТИФИКАТОР(ЗНАЧЕНИЕ(ИмяМетаданных.ПустаяСсылка)) для быстрых проверок «на месте».
  2. Используйте передачу параметра Новый УникальныйИдентификатор("0000...") для создания универсального кода.
  3. Помните, что NULL не равен пустому ГУИДу.
  4. Старайтесь не использовать эту функцию в секции ГДЕ, если можно отфильтровать данные по обычной ссылке, чтобы сохранить высокую скорость работы запроса.
← На главную