Разработка и Конфигурация · 11 мин
Как сравнить ссылки в запросе 1С
Как сравнить ссылки в запросе 1С: операторы равенства, ЗНАЧЕНИЕ(), ССЫЛКА, В ИЕРАРХИИ, сравнение составных типов. Примеры кода, ошибки и проверка результата.
Сравнение ссылок — одна из самых частых операций в запросах 1С: отбор документов по контрагенту, фильтрация по номенклатуре, проверка владельца справочника. При этом у разработчиков регулярно возникают ошибки: запрос не находит данные, падает с ошибкой несоответствия типов или работает медленно из-за неправильного сравнения составных полей.
Причина почти всегда в том, что ссылка в 1С — это не строка и не GUID, а типизированный объект, и сравнивать её нужно с учётом типа. Запрос вида ГДЕ Контрагент = "ООО Ромашка" не вернёт ничего, даже если такой контрагент существует, потому что строка никогда не равна ссылке.
Ниже разобраны все рабочие способы сравнения ссылок в языке запросов 1С: через параметр, через литерал ЗНАЧЕНИЕ(), по представлению, по GUID, сравнение составных типов и иерархии. Для каждого способа указаны условия применения, ограничения и типичные ошибки.
Как устроено сравнение ссылок в языке запросов
Ссылка в 1С — это значение строго определённого типа: СправочникСсылка.Контрагенты, ДокументСсылка.РеализацияТоваровУслуг и т.д. Две ссылки равны, только если совпадает и тип, и внутренний идентификатор (GUID). Поэтому оператор = в запросе сравнивает именно пару «тип + идентификатор», а не наименование или код.
Из этого следуют два практических вывода. Первый: ссылка на элемент справочника «Контрагенты» никогда не будет равна ссылке на элемент справочника «Организации», даже если у них совпадают наименования. Второй: пустая ссылка одного типа не равна пустой ссылке другого типа, что важно при проверках на незаполненность.
Сравнение ссылки с параметром запроса
Самый универсальный и рекомендуемый способ — передать ссылку в запрос через параметр и сравнить оператором =. Это работает быстро, использует индексы и не зависит от представления объекта.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Реализация.Ссылка КАК Документ,
| Реализация.СуммаДокумента КАК Сумма
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Реализация
|ГДЕ
| Реализация.Контрагент = &Контрагент";
Запрос.УстановитьПараметр("Контрагент", КонтрагентСсылка);
Результат = Запрос.Выполнить();
Ключевое условие: в параметр должно попасть значение именно ссылочного типа, а не строка, не GUID и не объект СправочникОбъект. Если переменная КонтрагентСсылка содержит Неопределено или строку, запрос либо вернёт пустой результат, либо завершится ошибкой в зависимости от режима совместимости.
Проверить тип значения перед установкой параметра можно функцией ТипЗнч():
Если ТипЗнч(КонтрагентСсылка) = Тип("СправочникСсылка.Контрагенты") Тогда
Запрос.УстановитьПараметр("Контрагент", КонтрагентСсылка);
Иначе
ВызватьИсключение "Ожидалась ссылка на справочник ""Контрагенты""";
КонецЕсли;
Литерал ЗНАЧЕНИЕ() и сравнение без параметра
Если ссылка известна на этапе разработки — чаще всего это предопределённый элемент справочника или план видов характеристик — её можно указать прямо в тексте запроса оператором ЗНАЧЕНИЕ():
ВЫБРАТЬ
Номенклатура.Ссылка
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.ВидНоменклатуры = ЗНАЧЕНИЕ(Справочник.ВидыНоменклатуры.Услуга)
Этот же оператор используют для сравнения с пустой ссылкой конкретного типа, когда нужно отобрать записи с незаполненным реквизитом:
ГДЕ
Реализация.Договор = ЗНАЧЕНИЕ(Справочник.ДоговорыКонтрагентов.ПустаяСсылка)
Ограничение способа: в ЗНАЧЕНИЕ() можно обратиться только к предопределённому элементу по его имени в конфигураторе. Обычный (непредопределённый) элемент так указать нельзя — компилятор запроса выдаст ошибку «Поле не найдено». Для обычных элементов используйте параметр или поиск по коду/наименованию.
Сравнение через представление, код и GUID
Сравнение по наименованию или коду
Когда на входе есть только строка (например, данные из файла обмена), сравнивать её со ссылкой напрямую нельзя. Вариант — сравнить строку с реквизитом объекта: ГДЕ Номенклатура.Наименование = &Наименование или ГДЕ Номенклатура.Код = &Код. Учтите, что наименования могут дублироваться, а коды — отличаться по длине и ведущим нулям, поэтому такой отбор ненадёжен как способ идентификации.
Сравнение по GUID
В языке запросов нет прямого доступа к GUID ссылки, поэтому сравнение «по идентификатору» делают в два шага: сначала в коде получают ссылку методом ПолучитьСсылку(), затем передают её параметром:
Идентификатор = Новый УникальныйИдентификатор(СтрокаGUID);
СсылкаНаОбъект = Справочники.Контрагенты.ПолучитьСсылку(Идентификатор);
Запрос.УстановитьПараметр("Контрагент", СсылкаНаОбъект);
Если объекта с таким GUID в базе нет, полученная ссылка будет «битой» — запрос отработает, но просто ничего не найдёт. Проверить существование объекта можно через СсылкаНаОбъект.ПолучитьОбъект() (вернёт Неопределено) или запросом по этой ссылке.
- 1Создайте УникальныйИдентификатор из строки: Новый УникальныйИдентификатор(СтрокаGUID)
- 2Получите ссылку: Справочники.Контрагенты.ПолучитьСсылку(Идентификатор)
- 3Проверьте существование объекта через ПолучитьОбъект() — при необходимости
- 4Передайте ссылку параметром в запрос и сравните оператором =
- 5Выполните запрос и убедитесь, что выборка непустая
Сравнение реквизитов составного типа
Если реквизит имеет составной тип (например, «Контрагент или Организация», «ЛюбаяСсылка»), простое сравнение = &Параметр работает, но с оговорками: оно сработает только для записей, где тип значения совпадает с типом параметра. Проблемы начинаются, когда нужно сравнить поле с конкретной ссылкой и одновременно отбросить значения других типов, или когда платформа не может построить эффективный план запроса.
Стандартный приём — привести поле к нужному типу оператором ВЫРАЗИТЬ:
ВЫБРАТЬ
Операция.Ссылка
ИЗ
Документ.Операция КАК Операция
ГДЕ
ВЫРАЗИТЬ(Операция.Контрагент КАК Справочник.Контрагенты) = &Контрагент
Значения других типов после приведения станут пустыми ссылками указанного типа и не пройдут условие равенства реальной ссылке. Альтернатива — сравнение через ССЫЛКА в соединении или проверка типа через ТИПЗНАЧЕНИЯ():
ГДЕ
ТИПЗНАЧЕНИЯ(Операция.Контрагент) = ТИП(Справочник.Контрагенты)
И Операция.Контрагент = &Контрагент
Сравнение с учётом иерархии и списков ссылок
Для иерархических справочников часто нужно отобрать не один элемент, а всю ветку. Оператор В ИЕРАРХИИ сравнивает ссылку с родителем с учётом всех уровней вложенности:
ВЫБРАТЬ
Номенклатура.Ссылка
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Ссылка В ИЕРАРХИИ(&Группа)
Для сравнения с несколькими ссылками используйте оператор В со списком значений или массивом, переданным параметром: ГДЕ Реализация.Контрагент В (&СписокКонтрагентов). Массив ссылок одного типа обрабатывается эффективно; смешивать в одном массиве ссылки разных типов не стоит — поведение зависит от типа сравниваемого поля.
Способы сравнения ссылок
Универсальный и быстрый способ для любой ссылки, полученной в коде. Требует строгого контроля типа параметра.
Подходит для предопределённых элементов и пустых ссылок. Ломается при переименовании элемента в конфигураторе.
Единственный вариант, когда ссылки нет, а есть строка из внешних данных. Ненадёжен из-за дублей и различий форматов.
Для интеграций по идентификатору. Требует предварительного кода и проверки существования объекта.
Для отбора по ветке справочника или по набору ссылок. Не заменяет точное равенство, решает другую задачу.
Проверка результата и типичные ошибки
После написания условия сравнения проверьте запрос на контрольных данных: заведите документ с известным контрагентом и убедитесь, что он попадает в выборку, а документ другого контрагента — нет. Пустой результат при заведомо подходящих данных — почти всегда признак сравнения несовместимых типов.
Также полезно вывести в выборку само сравниваемое поле и ТИПЗНАЧЕНИЯ(Поле) — это сразу показывает, какого типа значения реально хранятся в базе, и объясняет «непонятные» промахи отбора.
Как проверить результат
ТипЗнч() возвращает ожидаемый ссылочный тип
Неопределено, строка или объект вместо ссылки
Документ с известной ссылкой найден, чужие — нет
Пустой результат или лишние строки
ТИПЗНАЧЕНИЯ(Поле) совпадает с типом параметра
В поле хранятся значения других типов
Тип пустой ссылки в ЗНАЧЕНИЕ() совпадает с типом поля
Использована пустая ссылка другого справочника
Частые вопросы
Можно ли сравнить две ссылки оператором <> (не равно)?
Да, операторы <> и != работают с ссылками так же, как =, с учётом типа и идентификатора. Учтите, что условие «не равно» не отберёт записи, где поле имеет другой тип или значение NULL в результате левого соединения — такие строки нужно обрабатывать отдельно через ЕСТЬ NULL.
Как сравнить ссылку с NULL в запросе?
Прямое сравнение «ссылка = NULL» всегда ложно. Используйте операторы ЕСТЬ NULL / НЕ ЕСТЬ NULL, а для замены NULL на пустую ссылку конкретного типа — функцию ЕСТЬNULL(Поле, ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка)).
Почему запрос с условием по ссылке работает медленно?
Частые причины: применение ВЫРАЗИТЬ или функций к полю в условии, что блокирует использование индекса; отбор по неиндексированному реквизиту; сравнение по представлению вместо ссылки. Проверьте план запроса в консоли и по возможности сравнивайте поле напрямую с параметром.
Как сравнить ссылку в СКД, а не в ручном запросе?
В схеме компоновки данных сравнение задаётся в отборе: поле ссылочного типа, вид сравнения «Равно», значение — параметр или конкретный элемент, выбранный из списка. Пользовательский отбор в режиме предприятия сам формирует корректное сравнение по типу, вручную писать условие не нужно.
Чем отличается сравнение в запросе от сравнения в коде?
В модуле ссылки сравнивают оператором = напрямую (Ссылка1 = Ссылка2) — это то же сравнение типа и GUID. Отличие в том, что в коде доступны методы вроде Пустая() и ПолучитьОбъект(), а в запросе — только операторы языка запросов, поэтому часть логики приходится переносить в параметры.
Что важно запомнить
Ссылка в запросе 1С сравнивается по паре «тип + GUID», поэтому сравнивать её можно только со значением того же ссылочного типа: параметром, ЗНАЧЕНИЕ() или результатом ПолучитьСсылку(). Строки и GUID напрямую не подходят, составные поля требуют ВЫРАЗИТЬ или ТИПЗНАЧЕНИЯ, пустую ссылку указывайте строго того же типа, что и поле. Контрольный прогон на известных данных — обязательная проверка корректности условия.