Как в запросе 1С сравнить ссылку (справочник) со строковым значением

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

В процессе разработки на платформе 1С:Предприятие 8 программисты часто сталкиваются с ситуацией, когда в параметрах запроса имеется строковое значение (например, название организации или артикул товара), а в базе данных соответствующее поле имеет тип Ссылка. Прямое сравнение Справочник.Ссылка = &Строка приведет к ошибке несовместимости типов или к пустому результату. В данной статье мы подробно разберем, как правильно реализовать такое сравнение, какие методы существуют и какой из них является наиболее оптимальным с точки зрения производительности.

Способ 1. Обращение к наименованию через точку (Разыменование)

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

Рассмотрим пример, где нам нужно найти сотрудников конкретной организации, имея на руках только её название в переменной Заказчик:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Сотрудники.Ссылка КАК Ссылка,
    |   Сотрудники.Наименование КАК Наименование
    |ИЗ
    |   Справочник.СотрудникиЗаказчика КАК Сотрудники
    |ГДЕ
    |   Сотрудники.Организация.Наименование = &ОрганизацияНаименование";

Запрос.УстановитьПараметр("ОрганизацияНаименование", Заказчик);
Выборка = Запрос.Выполнить().Выбрать();

Преимущества: Простота написания и читаемость кода.

Недостатки: Низкая надежность. Если в справочнике Организации окажутся два элемента с одинаковым наименованием, запрос выберет сотрудников обеих организаций. Также стоит учитывать вопросы производительности, которые мы разберем ниже.

Способ 2. Использование оператора ПОДОБНО и виртуального поля Представление

Если нам нужно найти данные по частичному совпадению строки или если мы хотим использовать системное представление объекта, можно прибегнуть к оператору ПОДОБНО. Проанализируем ситуацию, когда поиск ведется по маске:


|ГДЕ
|   Сотрудники.Организация.Представление ПОДОБНО ""%"" + &Организация + ""%""

Здесь используется поле Представление. Важно понимать, что это поле является виртуальным. На уровне СУБД 1С преобразует его в выборку основной текстовой колонки справочника (обычно это Наименование или Код). Использование ПОДОБНО в сочетании с Представление крайне не рекомендуется на больших таблицах, так как это гарантированно приводит к полному сканированию таблицы (Full Table Scan) в SQL, игнорируя индексы.

Способ 3. Предварительный поиск ссылки (Лучшая практика)

Проанализируем наиболее правильный подход с точки зрения архитектуры 1С. Вместо того чтобы заставлять СУБД сопоставлять строки в сложном запросе, мы можем заранее найти ссылку на объект в коде 1С:Предприятия и передать её в запрос как готовый параметр.

Выясним, как это выглядит на практике:

  1. Сначала находим ссылку на организацию по строковому названию.
  2. Проверяем, найдена ли организация.
  3. Передаем найденную ссылку в параметр запроса.

// 1. Ищем ссылку по строке
СсылкаОрганизация = Справочники.Организации.НайтиПоНаименованию(Заказчик);

Если СсылкаОрганизация.Пустая() Тогда
    Сообщить("Организация с таким названием не найдена!");
    Возврат;
КонецЕсли;

// 2. Выполняем запрос, сравнивая ссылки (самый быстрый способ)
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Сотрудники.Ссылка
    |ИЗ
    |   Справочник.СотрудникиЗаказчика КАК Сотрудники
    |ГДЕ
    |   Сотрудники.Организация = &Организация";

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

Этот метод считается эталонным, так как сравнение по ссылке внутри СУБД происходит по внутреннему идентификатору (UUID), который всегда проиндексирован и работает максимально быстро.

Почему обращение через точку («две точки») может тормозить?

Рассмотрим техническую сторону вопроса производительности, которую часто обсуждают на форумах. Когда вы пишете Сотрудники.Организация.Наименование, платформа автоматически генерирует LEFT OUTER JOIN (левое соединение) с таблицей справочника организаций.

Проанализируем риски:

Использование функции ВЫРАЗИТЬ

В некоторых обсуждениях встречается совет использовать ВЫРАЗИТЬ(Поле КАК СТРОКА). Важно помнить: в языке запросов 1С функция ВЫРАЗИТЬ не умеет превращать Ссылку в Строку. Она предназначена либо для ограничения длины строк неограниченной длины, либо для приведения составного типа к конкретному ссылочному типу. При необходимости соединять или фильтровать данные таким образом можно применить решение для сравнения строки с представлением ссылки в запросе.

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


"ВЫБРАТЬ
|   Сотрудники.Ссылка
|ИЗ
|   Справочник.СотрудникиЗаказчика КАК Сотрудники
|   ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Организации КАК ТаблицаОрганизаций
|       ПО Сотрудники.Организация = ТаблицаОрганизаций.Ссылка
|ГДЕ
|   ТаблицаОрганизаций.Наименование = &ОрганизацияНаименование"

Резюме: Если у вас есть возможность найти ссылку в коде до выполнения запроса — делайте это. Это избавит вас от проблем с уникальностью наименований и обеспечит максимальную скорость работы программы. Если же поиск по строке неизбежен внутри запроса, используйте прямое обращение к .Наименование, предварительно убедившись, что поле не является составным.

← На главную