К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как сравнить ссылки в запросе 1С

Как сравнить ссылки в запросе 1С: операторы равенства, ЗНАЧЕНИЕ(), ССЫЛКА, В ИЕРАРХИИ, сравнение составных типов. Примеры кода, ошибки и проверка результата.

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

Причина почти всегда в том, что ссылка в 1С — это не строка и не GUID, а типизированный объект, и сравнивать её нужно с учётом типа. Запрос вида ГДЕ Контрагент = "ООО Ромашка" не вернёт ничего, даже если такой контрагент существует, потому что строка никогда не равна ссылке.

Ниже разобраны все рабочие способы сравнения ссылок в языке запросов 1С: через параметр, через литерал ЗНАЧЕНИЕ(), по представлению, по GUID, сравнение составных типов и иерархии. Для каждого способа указаны условия применения, ограничения и типичные ошибки.

Как устроено сравнение ссылок в языке запросов

Ссылка в 1С — это значение строго определённого типа: СправочникСсылка.Контрагенты, ДокументСсылка.РеализацияТоваровУслуг и т.д. Две ссылки равны, только если совпадает и тип, и внутренний идентификатор (GUID). Поэтому оператор = в запросе сравнивает именно пару «тип + идентификатор», а не наименование или код.

Из этого следуют два практических вывода. Первый: ссылка на элемент справочника «Контрагенты» никогда не будет равна ссылке на элемент справочника «Организации», даже если у них совпадают наименования. Второй: пустая ссылка одного типа не равна пустой ссылке другого типа, что важно при проверках на незаполненность.

Сравнение ссылки с параметром запроса

Самый универсальный и рекомендуемый способ — передать ссылку в запрос через параметр и сравнить оператором =. Это работает быстро, использует индексы и не зависит от представления объекта.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Реализация.Ссылка КАК Документ,

| Реализация.СуммаДокумента КАК Сумма

|ИЗ

| Документ.РеализацияТоваровУслуг КАК Реализация

|ГДЕ

| Реализация.Контрагент = &Контрагент";

Запрос.УстановитьПараметр("Контрагент", КонтрагентСсылка);

Результат = Запрос.Выполнить();

Ключевое условие: в параметр должно попасть значение именно ссылочного типа, а не строка, не GUID и не объект СправочникОбъект. Если переменная КонтрагентСсылка содержит Неопределено или строку, запрос либо вернёт пустой результат, либо завершится ошибкой в зависимости от режима совместимости.

Проверить тип значения перед установкой параметра можно функцией ТипЗнч():

Если ТипЗнч(КонтрагентСсылка) = Тип("СправочникСсылка.Контрагенты") Тогда

Запрос.УстановитьПараметр("Контрагент", КонтрагентСсылка);

Иначе

ВызватьИсключение "Ожидалась ссылка на справочник ""Контрагенты""";

КонецЕсли;

Литерал ЗНАЧЕНИЕ() и сравнение без параметра

Если ссылка известна на этапе разработки — чаще всего это предопределённый элемент справочника или план видов характеристик — её можно указать прямо в тексте запроса оператором ЗНАЧЕНИЕ():

ВЫБРАТЬ

Номенклатура.Ссылка

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

Номенклатура.ВидНоменклатуры = ЗНАЧЕНИЕ(Справочник.ВидыНоменклатуры.Услуга)

Этот же оператор используют для сравнения с пустой ссылкой конкретного типа, когда нужно отобрать записи с незаполненным реквизитом:

ГДЕ

Реализация.Договор = ЗНАЧЕНИЕ(Справочник.ДоговорыКонтрагентов.ПустаяСсылка)

Ограничение способа: в ЗНАЧЕНИЕ() можно обратиться только к предопределённому элементу по его имени в конфигураторе. Обычный (непредопределённый) элемент так указать нельзя — компилятор запроса выдаст ошибку «Поле не найдено». Для обычных элементов используйте параметр или поиск по коду/наименованию.

Сравнение через представление, код и GUID

Сравнение по наименованию или коду

Когда на входе есть только строка (например, данные из файла обмена), сравнивать её со ссылкой напрямую нельзя. Вариант — сравнить строку с реквизитом объекта: ГДЕ Номенклатура.Наименование = &Наименование или ГДЕ Номенклатура.Код = &Код. Учтите, что наименования могут дублироваться, а коды — отличаться по длине и ведущим нулям, поэтому такой отбор ненадёжен как способ идентификации.

Сравнение по GUID

В языке запросов нет прямого доступа к GUID ссылки, поэтому сравнение «по идентификатору» делают в два шага: сначала в коде получают ссылку методом ПолучитьСсылку(), затем передают её параметром:

Идентификатор = Новый УникальныйИдентификатор(СтрокаGUID);

СсылкаНаОбъект = Справочники.Контрагенты.ПолучитьСсылку(Идентификатор);

Запрос.УстановитьПараметр("Контрагент", СсылкаНаОбъект);

Если объекта с таким GUID в базе нет, полученная ссылка будет «битой» — запрос отработает, но просто ничего не найдёт. Проверить существование объекта можно через СсылкаНаОбъект.ПолучитьОбъект() (вернёт Неопределено) или запросом по этой ссылке.

Сравнение ссылки по строке GUID
  1. 1
    Создайте УникальныйИдентификатор из строки: Новый УникальныйИдентификатор(СтрокаGUID)
  2. 2
    Получите ссылку: Справочники.Контрагенты.ПолучитьСсылку(Идентификатор)
  3. 3
    Проверьте существование объекта через ПолучитьОбъект() — при необходимости
  4. 4
    Передайте ссылку параметром в запрос и сравните оператором =
  5. 5
    Выполните запрос и убедитесь, что выборка непустая

Сравнение реквизитов составного типа

Если реквизит имеет составной тип (например, «Контрагент или Организация», «ЛюбаяСсылка»), простое сравнение = &Параметр работает, но с оговорками: оно сработает только для записей, где тип значения совпадает с типом параметра. Проблемы начинаются, когда нужно сравнить поле с конкретной ссылкой и одновременно отбросить значения других типов, или когда платформа не может построить эффективный план запроса.

Стандартный приём — привести поле к нужному типу оператором ВЫРАЗИТЬ:

ВЫБРАТЬ

Операция.Ссылка

ИЗ

Документ.Операция КАК Операция

ГДЕ

ВЫРАЗИТЬ(Операция.Контрагент КАК Справочник.Контрагенты) = &Контрагент

Значения других типов после приведения станут пустыми ссылками указанного типа и не пройдут условие равенства реальной ссылке. Альтернатива — сравнение через ССЫЛКА в соединении или проверка типа через ТИПЗНАЧЕНИЯ():

ГДЕ

ТИПЗНАЧЕНИЯ(Операция.Контрагент) = ТИП(Справочник.Контрагенты)

И Операция.Контрагент = &Контрагент

Сравнение с учётом иерархии и списков ссылок

Для иерархических справочников часто нужно отобрать не один элемент, а всю ветку. Оператор В ИЕРАРХИИ сравнивает ссылку с родителем с учётом всех уровней вложенности:

ВЫБРАТЬ

Номенклатура.Ссылка

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

Номенклатура.Ссылка В ИЕРАРХИИ(&Группа)

Для сравнения с несколькими ссылками используйте оператор В со списком значений или массивом, переданным параметром: ГДЕ Реализация.Контрагент В (&СписокКонтрагентов). Массив ссылок одного типа обрабатывается эффективно; смешивать в одном массиве ссылки разных типов не стоит — поведение зависит от типа сравниваемого поля.

Способы сравнения ссылок

Параметр + оператор =

Универсальный и быстрый способ для любой ссылки, полученной в коде. Требует строгого контроля типа параметра.

ЗНАЧЕНИЕ() в тексте запроса

Подходит для предопределённых элементов и пустых ссылок. Ломается при переименовании элемента в конфигураторе.

По коду или наименованию

Единственный вариант, когда ссылки нет, а есть строка из внешних данных. Ненадёжен из-за дублей и различий форматов.

Через ПолучитьСсылку(GUID)

Для интеграций по идентификатору. Требует предварительного кода и проверки существования объекта.

В ИЕРАРХИИ / В (список)

Для отбора по ветке справочника или по набору ссылок. Не заменяет точное равенство, решает другую задачу.

Проверка результата и типичные ошибки

После написания условия сравнения проверьте запрос на контрольных данных: заведите документ с известным контрагентом и убедитесь, что он попадает в выборку, а документ другого контрагента — нет. Пустой результат при заведомо подходящих данных — почти всегда признак сравнения несовместимых типов.

Также полезно вывести в выборку само сравниваемое поле и ТИПЗНАЧЕНИЯ(Поле) — это сразу показывает, какого типа значения реально хранятся в базе, и объясняет «непонятные» промахи отбора.

Типичные ошибки
01
Сравнение ссылки со строкой: ГДЕ Контрагент = "ООО Ромашка" — выборка всегда пустая, потому что типы не совпадают
02
Передача в параметр СправочникОбъект вместо ссылки — лишний объект в памяти и риск ошибки; передавайте Объект.Ссылка
03
Сравнение с пустой ссылкой не того типа: ЗНАЧЕНИЕ(Справочник.Организации.ПустаяСсылка) для поля типа Контрагенты не найдёт незаполненные значения
04
Игнорирование составного типа: равенство без ВЫРАЗИТЬ или проверки ТИПЗНАЧЕНИЯ даёт неочевидные результаты на смешанных данных
05
Отбор по наименованию как замена ссылке — дубли наименований приводят к отбору чужих объектов
Контрольные точки

Как проверить результат

Тип значения параметра
Норма

ТипЗнч() возвращает ожидаемый ссылочный тип

Тревожный признак

Неопределено, строка или объект вместо ссылки

Выборка на контрольном объекте
Норма

Документ с известной ссылкой найден, чужие — нет

Тревожный признак

Пустой результат или лишние строки

Тип значений поля в базе
Норма

ТИПЗНАЧЕНИЯ(Поле) совпадает с типом параметра

Тревожный признак

В поле хранятся значения других типов

Сравнение с пустой ссылкой
Норма

Тип пустой ссылки в ЗНАЧЕНИЕ() совпадает с типом поля

Тревожный признак

Использована пустая ссылка другого справочника

Частые вопросы

Можно ли сравнить две ссылки оператором <> (не равно)?

Да, операторы <> и != работают с ссылками так же, как =, с учётом типа и идентификатора. Учтите, что условие «не равно» не отберёт записи, где поле имеет другой тип или значение NULL в результате левого соединения — такие строки нужно обрабатывать отдельно через ЕСТЬ NULL.

Как сравнить ссылку с NULL в запросе?

Прямое сравнение «ссылка = NULL» всегда ложно. Используйте операторы ЕСТЬ NULL / НЕ ЕСТЬ NULL, а для замены NULL на пустую ссылку конкретного типа — функцию ЕСТЬNULL(Поле, ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка)).

Почему запрос с условием по ссылке работает медленно?

Частые причины: применение ВЫРАЗИТЬ или функций к полю в условии, что блокирует использование индекса; отбор по неиндексированному реквизиту; сравнение по представлению вместо ссылки. Проверьте план запроса в консоли и по возможности сравнивайте поле напрямую с параметром.

Как сравнить ссылку в СКД, а не в ручном запросе?

В схеме компоновки данных сравнение задаётся в отборе: поле ссылочного типа, вид сравнения «Равно», значение — параметр или конкретный элемент, выбранный из списка. Пользовательский отбор в режиме предприятия сам формирует корректное сравнение по типу, вручную писать условие не нужно.

Чем отличается сравнение в запросе от сравнения в коде?

В модуле ссылки сравнивают оператором = напрямую (Ссылка1 = Ссылка2) — это то же сравнение типа и GUID. Отличие в том, что в коде доступны методы вроде Пустая() и ПолучитьОбъект(), а в запросе — только операторы языка запросов, поэтому часть логики приходится переносить в параметры.

Итог

Что важно запомнить

Ссылка в запросе 1С сравнивается по паре «тип + GUID», поэтому сравнивать её можно только со значением того же ссылочного типа: параметром, ЗНАЧЕНИЕ() или результатом ПолучитьСсылку(). Строки и GUID напрямую не подходят, составные поля требуют ВЫРАЗИТЬ или ТИПЗНАЧЕНИЯ, пустую ссылку указывайте строго того же типа, что и поле. Контрольный прогон на известных данных — обязательная проверка корректности условия.