При написании запросов в платформе 1С:Предприятие начинающие разработчики часто сталкиваются с вопросом: можно ли динамически найти нужный элемент прямо внутри текста запроса, вызвав метод объектной модели, например Справочники.Номенклатура.НайтиПоНаименованию("Шоколад") внутри функции ЗНАЧЕНИЕ()?
Рассмотрим подробно, почему такой синтаксис не поддерживается платформой, как устроена работа языка запросов на стороне системы управления базами данных (СУБД) и какие существующие механизмы позволяют решить эту задачу правильно и эффективно.
Выясним причину технического ограничения. Текст запроса в 1С транслируется платформой в инструкцию на языке SQL и передается для исполнения непосредственно серверу баз данных (Microsoft SQL Server, PostgreSQL и др.). Вызовы методов объектной модели 1С, такие как НайтиПоНаименованию(), ПустаяСсылка() или функции общих модулей, являются частью встроенного языка 1С и выполняются на сервере приложений или в клиенте.
СУБД ничего не знает о методах встроенного языка 1С и не может их выполнить. По этой причине прямое использование объектных методов в тексте запроса категорически невозможно.
Что касается функции ЗНАЧЕНИЕ(), она обрабатывается платформой ещё на этапе компиляции запроса и принимает только строго зафиксированные идентификаторы. В неё разрешено передавать исключительно:
ВидДвиженияНакопления.Приход).Справочник.Номенклатура.ПустаяСсылка).Тип.Число или Тип.Справочник.Номенклатура).Передавать в функцию ЗНАЧЕНИЕ() вызовы функций, переменные или динамические строки нельзя.
Проанализируем наиболее распространенный и стандартный вариант. Если вам необходимо найти элемент по наименованию и применить его в качестве фильтра в запросе, правильным решением будет предварительно вычислить значение во встроенном языке и передать его в запрос через параметр.
Разберем пример кода:
СсылкаНаЭлемент = Справочники.Номенклатура.НайтиПоНаименованию("Шоколад");
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка = &ИскомаяСсылка";
Запрос.УстановитьПараметр("ИскомаяСсылка", СсылкаНаЭлемент);
Результат = Запрос.Выполнить();
Этот способ является универсальным, безопасным и не создает лишней нагрузки при компиляции планов запросов в СУБД.
Посмотрим на ситуацию под другим углом: если задача состоит в том, чтобы найти данные в базе без предварительного обращения к объектам через встроенный язык, отбор по наименованию или другим реквизитам можно выполнить прямо в запросе.
Рассмотрим вариант с прямым отбором по полю Наименование:
ВЫБРАТЬ
Товары.Ссылка КАК Ссылка,
Товары.Артикул КАК Артикул
ИЗ
Справочник.Номенклатура КАК Товары
ГДЕ
Товары.Наименование = "Шоколад"
Также можно использовать подзапросы или оператор В, если требуется проверить вхождение элемента в список или выборку:
ВЫБРАТЬ
ДокументТабЧасть.Ссылка КАК Документ,
ДокументТабЧасть.Номенклатура КАК Номенклатура
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК ДокументТабЧасть
ГДЕ
ДокументТабЧасть.Номенклатура В
(ВЫБРАТЬ
Номенклатура.Ссылка
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Наименование = "Шоколад")
Важное примечание по производительности: частая передача строковых литералов непосредственно в текст запроса (например, "Шоколад") препятствует кэшированию планов выполнения в СУБД. По возможности используйте передачу строки через параметр (Товары.Наименование = &ИскомоеНаименование). Кроме того, избегайте условий вида ПОДОБНО "%Шоколад%" на больших объемах данных, так как начинающийся с процента шаблон отключает использование B-tree индексов по текстовым полям.
Если искомый элемент справочника является ключевым для бизнес-логики системы, его стоит сделать предопределенным в конфигураторе. В таком случае к нему можно обратиться напрямую из текста запроса с помощью функции ЗНАЧЕНИЕ() без передачи параметров.
Рассмотрим пример обращения к предопределенному элементу:
ВЫБРАТЬ
Товары.Ссылка КАК Ссылка,
Товары.Цена КАК Цена
ИЗ
Справочник.Номенклатура КАК Товары
ГДЕ
Товары.Ссылка = ЗНАЧЕНИЕ(Справочник.Номенклатура.Шоколад)
Если разработка ведется в рамках Системы компоновки данных (СКД), платформа предоставляет удобный механизм вычисления параметров. В схеме компоновки данных на вкладке Параметры в колонке Выражение можно напрямую прописать вызов метода 1С.
Пример выражения в параметре СКД:
Справочники.Номенклатура.НайтиПоНаименованию("Шоколад")
Платформа автоматически вычислит это выражение на сервере приложений перед исполнением отчета и подставит полученную ссылку в соответствующий параметр запроса без необходимости писать код программы вручную.