Можно ли использовать методы объектов в секции ГДЕ запроса 1С

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

При написании запросов в платформе 1С:Предприятие начинающие разработчики часто сталкиваются с вопросом: можно ли динамически найти нужный элемент прямо внутри текста запроса, вызвав метод объектной модели, например Справочники.Номенклатура.НайтиПоНаименованию("Шоколад") внутри функции ЗНАЧЕНИЕ()?

Рассмотрим подробно, почему такой синтаксис не поддерживается платформой, как устроена работа языка запросов на стороне системы управления базами данных (СУБД) и какие существующие механизмы позволяют решить эту задачу правильно и эффективно.

Почему нельзя использовать методы объектов в запросах 1С

Выясним причину технического ограничения. Текст запроса в 1С транслируется платформой в инструкцию на языке SQL и передается для исполнения непосредственно серверу баз данных (Microsoft SQL Server, PostgreSQL и др.). Вызовы методов объектной модели 1С, такие как НайтиПоНаименованию(), ПустаяСсылка() или функции общих модулей, являются частью встроенного языка 1С и выполняются на сервере приложений или в клиенте.

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

Что касается функции ЗНАЧЕНИЕ(), она обрабатывается платформой ещё на этапе компиляции запроса и принимает только строго зафиксированные идентификаторы. В неё разрешено передавать исключительно:

  1. Предопределённые элементы справочников, планов видов характеристик, планов счетов и планов видов расчёта.
  2. Значения перечислений (как прикладных, так и системных, например ВидДвиженияНакопления.Приход).
  3. Пустые ссылки ссылочных типов данных (например, Справочник.Номенклатура.ПустаяСсылка).
  4. Обозначения типов (например, Тип.Число или Тип.Справочник.Номенклатура).

Передавать в функцию ЗНАЧЕНИЕ() вызовы функций, переменные или динамические строки нельзя.

Способ 1. Передача значения через параметр запроса

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

Разберем пример кода:


СсылкаНаЭлемент = Справочники.Номенклатура.НайтиПоНаименованию("Шоколад");

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

Запрос.УстановитьПараметр("ИскомаяСсылка", СсылкаНаЭлемент);
Результат = Запрос.Выполнить();

Этот способ является универсальным, безопасным и не создает лишней нагрузки при компиляции планов запросов в СУБД.

Способ 2. Отбор по реквизитам непосредственно в запросе

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

Рассмотрим вариант с прямым отбором по полю Наименование:


ВЫБРАТЬ
	Товары.Ссылка КАК Ссылка,
	Товары.Артикул КАК Артикул
ИЗ
	Справочник.Номенклатура КАК Товары
ГДЕ
	Товары.Наименование = "Шоколад"

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


ВЫБРАТЬ
	ДокументТабЧасть.Ссылка КАК Документ,
	ДокументТабЧасть.Номенклатура КАК Номенклатура
ИЗ
	Документ.РеализацияТоваровУслуг.Товары КАК ДокументТабЧасть
ГДЕ
	ДокументТабЧасть.Номенклатура В
		(ВЫБРАТЬ
			Номенклатура.Ссылка
		ИЗ
			Справочник.Номенклатура КАК Номенклатура
		ГДЕ
			Номенклатура.Наименование = "Шоколад")

Важное примечание по производительности: частая передача строковых литералов непосредственно в текст запроса (например, "Шоколад") препятствует кэшированию планов выполнения в СУБД. По возможности используйте передачу строки через параметр (Товары.Наименование = &ИскомоеНаименование). Кроме того, избегайте условий вида ПОДОБНО "%Шоколад%" на больших объемах данных, так как начинающийся с процента шаблон отключает использование B-tree индексов по текстовым полям.

Способ 3. Использование предопределенных элементов

Если искомый элемент справочника является ключевым для бизнес-логики системы, его стоит сделать предопределенным в конфигураторе. В таком случае к нему можно обратиться напрямую из текста запроса с помощью функции ЗНАЧЕНИЕ() без передачи параметров.

Рассмотрим пример обращения к предопределенному элементу:


ВЫБРАТЬ
	Товары.Ссылка КАК Ссылка,
	Товары.Цена КАК Цена
ИЗ
	Справочник.Номенклатура КАК Товары
ГДЕ
	Товары.Ссылка = ЗНАЧЕНИЕ(Справочник.Номенклатура.Шоколад)

Способ 4. Использование выражений в параметрах СКД

Если разработка ведется в рамках Системы компоновки данных (СКД), платформа предоставляет удобный механизм вычисления параметров. В схеме компоновки данных на вкладке Параметры в колонке Выражение можно напрямую прописать вызов метода 1С.

Пример выражения в параметре СКД:

Справочники.Номенклатура.НайтиПоНаименованию("Шоколад")

Платформа автоматически вычислит это выражение на сервере приложений перед исполнением отчета и подставит полученную ссылку в соответствующий параметр запроса без необходимости писать код программы вручную.

← На главную