Как правильно установить отбор в запросе 1С по значению справочника без использования параметров?

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

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

Выясним причину синтаксической ошибки в функции ЗНАЧЕНИЕ()

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

Допустимые варианты использования функции ЗНАЧЕНИЕ():

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

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


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

Способ 1. Использование параметров запроса (стандарт разработки)

Разберем наиболее универсальный и правильный подход с точки зрения стандартов разработки 1С. Если элемент справочника не является предопределенным, значение ссылочного типа необходимо передавать через параметр с помощью метода УстановитьПараметр().

Рассмотри пример кода на встроенном языке:


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

Запрос.УстановитьПараметр("Статус", Справочники.Статусы.НайтиПоНаименованию("Подготовлено"));
Результат = Запрос.Выполнить();

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

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

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


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

Способ 3. Отбор по нескольким наименованиям (условие ИЛИ)

Рассмотрим ситуацию, когда необходимо выбрать записи, соответствующие нескольким статусам одновременно (например, «Подготовлено» или «ВРаботе»).

Для этого можно использовать оператор В со списком строковых значений, что гораздо понятнее и эффективнее использования конструкции ИЛИ или шаблонов поиска:


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

Также возможен вариант проверки на вхождение подстроки через оператор ПОДОБНО:


ГДЕ
	"ПодготовленоВРаботе" ПОДОБНО "%" + ЗаказПокупателя.Статусы.Наименование + "%"

Важные рекомендации по производительности

Проанализируем потенциальные узкие места при выполнении подобного рода запросов:

  1. Избегайте неявных соединений через точку без необходимости: Обращение ЗаказПокупателя.Ссылка.Проведен заставляет СУБД выполнять неявное левое соединение (LEFT JOIN) с таблицей шапки документа. Если обращаться к полям табличной части напрямую (например, ЗаказПокупателя.Статусы), лишних соединений не происходит.
  2. Осторожно с оператором ПОДОБНО и процентом в начале строки: Шаблон вида "%Текст%" полностью блокирует использование индексов таблиц в СУБД, что приводит к полному сканированию таблицы (Full Table Scan).
  3. Перевод статусов на перечисления: Если значения статусов фиксированы и участвуют в бизнес-логике, рекомендуем заменить справочник на объект Перечисление. Это исключит проблему поиска по наименованию и ускорит выполнение запросов.
← На главную