С выходом платформы «1С:Предприятие» версии 8.3.24 разработчики получили долгожданный инструмент — встроенную функцию языка запросов УНИКАЛЬНЫЙИДЕНТИФИКАТОР(). До этого момента получение строкового или типизированного идентификатора ссылки непосредственно в запросе было нетривиальной задачей, требовавшей либо постобработки в коде, либо сложных манипуляций с двоичными данными на уровне СУБД. Однако новая функция принесла и новые вопросы, в частности: как правильно сравнивать полученный результат с «пустым» идентификатором?
Разберем подробно, почему привычные способы сравнения не работают и как правильно организовать фильтрацию в различных сценариях.
Рассмотрим типичную ошибку начинающего разработчика. Проанализируем ситуацию: функция УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Ссылка) возвращает объект специального типа УникальныйИдентификатор, а не обычную строку. Поэтому попытка выполнить сравнение следующим образом приведет к ошибке или неверному результату:
// ТАК РАБОТАТЬ НЕ БУДЕТ
ГДЕ УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Т.Ссылка) = "00000000-0000-0000-0000-000000000000"
Платформа строго следит за типизацией. Поскольку слева от знака равенства находится тип УникальныйИдентификатор, то и справа должен быть объект того же типа. Простое текстовое представление ГУИДа для системы является всего лишь набором символов, а не идентификатором, что часто вызывает ошибки сравнения строки с представлением ссылки в запросе.
Самый быстрый и лаконичный способ отфильтровать пустые значения прямо в тексте запроса — это использование предопределенного значения пустой ссылки. Выясним причину, почему это работает: функция УНИКАЛЬНЫЙИДЕНТИФИКАТОР() может принимать в качестве аргумента пустую ссылку любого типа, возвращая при этом стандартный пустой ГУИД (все нули).
Рассмотрим пример правильного написания условия:
ВЫБРАТЬ
Продажи.Ссылка,
УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Продажи.Ссылка) КАК ГУИД
ИЗ
Документ.РеализацияТоваровУслуг КАК Продажи
ГДЕ
УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Продажи.Ссылка) <> УНИКАЛЬНЫЙИДЕНТИФИКАТОР(ЗНАЧЕНИЕ(Документ.РеализацияТоваровУслуг.ПустаяСсылка))
В данном примере мы сравниваем результат вычисления функции от текущей ссылки с результатом вычисления функции от пустой ссылки. Это «чистый» способ, не требующий передачи дополнительных параметров извне, напоминающий формирование текста запроса для работы с иерархией.
Многие разработчики придерживаются мнения, что вычисление констант лучше выносить за пределы текста запроса для повышения читаемости и «чистоты» кода. Проанализируем этот подход. Мы можем заранее подготовить пустой идентификатор в коде 1С и передать его в запрос.
Пример кода на встроенном языке (для ускорения написания можно использовать ИИ-помощника для генерации каркаса кода):
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Номенклатура.Ссылка) <> &ПустойУИД";
// Создаем пустой идентификатор
Запрос.УстановитьПараметр("ПустойУИД", Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000"));
Результат = Запрос.Выполнить();
Этот метод считается более универсальным, так как он позволяет избежать привязки к конкретному типу метаданных (нам не нужно указывать Документ.Реализация...ПустаяСсылка), к тому же удобно использовать список GUID объектов и готовый код для получения ссылок.
Посмотрим на ситуацию глубже. Часто функция УНИКАЛЬНЫЙИДЕНТИФИКАТОР() используется для полей, полученных в результате ЛЕВОЕ СОЕДИНЕНИЕ. Если для записи из левой таблицы не нашлось соответствия в правой, поле ссылки примет значение NULL.
Важно: в этом случае функция вернет NULL, а не пустой ГУИД из нулей! Следовательно, обычная проверка на неравенство пустому ГУИДу может пропустить такие записи. Проанализируем правильную конструкцию фильтра в таких случаях:
ГДЕ
(УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Т.Ссылка) <> &ПустойУИД
ИЛИ УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Т.Ссылка) ЕСТЬ НЕ NULL)
Или, что более правильно с точки зрения логики запроса, предварительно обрабатывать NULL функцией ЕСТЬNULL, но помните, что ЕСТЬNULL(Ссылка, ПустаяСсылка) вернет ссылку, которую потом уже можно превратить в идентификатор.
Рассмотрим вопрос производительности, который часто вызывает споры. Когда мы пишем ГДЕ УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Ссылка) <> ..., мы заставляем СУБД вычислять функцию для каждой строки таблицы. В терминах баз данных это делает условие «не-SARGable» (Search Argumentable).
Что это означает на практике?
_IDRRef (ссылка), так как значение обернуто в функцию. Вместо быстрого поиска по индексу (Index Seek) будет выполнено полное сканирование таблицы или индекса (Index Scan), что на больших объемах данных (миллионы строк) приведет к существенным задержкам.Рекомендация: Если ваша задача — просто отфильтровать пустые ссылки, всегда делайте это напрямую по полю ссылки, не используя функцию идентификатора в секции ГДЕ.
Сравним два варианта:
Плохо (медленно):
ГДЕ УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Т.Ссылка) <> &ПустойУИД
Хорошо (быстро):
ГДЕ Т.Ссылка <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
Функцию УНИКАЛЬНЫЙИДЕНТИФИКАТОР() лучше оставить для секции ВЫБРАТЬ, когда вам нужно именно отобразить или выгрузить строковый ID во внешнюю систему.
Выясним, как платформа 1С обеспечивает работу этой функции на разных движках БД. Несмотря на то, что для разработчика код выглядит одинаково, итоговый SQL-запрос будет отличаться:
binary(16). Платформа преобразует его в uniqueidentifier. Сравнение с пустым значением происходит на уровне двоичных данных 0x00000000....bytea для хранения ссылок. 1С генерирует последовательность функций для конвертации этого массива в стандартный UUID-формат Postgres.Таким образом, использование ЗНАЧЕНИЕ() или параметра одинаково эффективно интерпретируется платформой перед отправкой запроса в СУБД. Выбор между ними — это вопрос ваших стандартов разработки и предпочтений по чистоте кода.
Для фильтрации пустых ГУИДов в запросах 1С:
УНИКАЛЬНЫЙИДЕНТИФИКАТОР(ЗНАЧЕНИЕ(ИмяМетаданных.ПустаяСсылка)) для быстрых проверок «на месте».Новый УникальныйИдентификатор("0000...") для создания универсального кода.NULL не равен пустому ГУИДу.ГДЕ, если можно отфильтровать данные по обычной ссылке, чтобы сохранить высокую скорость работы запроса.