При написании запросов в платформе 1С разработчики иногда пытаются передать в текст запроса значение, полученное с помощью методов встроенного языка, например НайтиПоНаименованию() или НайтиПоКоду(). Попытка вызвать подобные методы внутри функции ЗНАЧЕНИЕ() приводит к синтаксической ошибке. Проанализируем причину возникновения ошибки, рассмотрим правильные способы отбора данных и выясним, как оптимизировать такие запросы для высокой производительности.
Функция ЗНАЧЕНИЕ() обрабатывается на этапе компиляции текста запроса и предназначена исключительно для обращения к статическим объектам метаданных. Внутри неё нельзя вызывать методы встроенного языка 1С, такие как Справочники.Статусы.НайтиПоНаименованию(...).
Допустимые варианты использования функции ЗНАЧЕНИЕ():
ЗНАЧЕНИЕ(Справочник.Статусы.Подготовлено)ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказов.Подготовлено)ЗНАЧЕНИЕ(Справочник.Статусы.ПустаяСсылка)ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)Посмотрим на пример корректного использования функции ЗНАЧЕНИЕ(), когда у справочника создан предопределенный элемент с именем Подготовлено:
ВЫБРАТЬ
ЗаказПокупателя.Ссылка КАК Ссылка,
ЗаказПокупателя.Статусы КАК Статусы,
ЗаказПокупателя.Номенклатура КАК Номенклатура,
ЗаказПокупателя.Количество КАК Количество
ИЗ
Документ.ЗаказПокупателя.Товары КАК ЗаказПокупателя
ГДЕ
ЗаказПокупателя.Ссылка.Проведен = ИСТИНА
И ЗаказПокупателя.Статусы = ЗНАЧЕНИЕ(Справочник.Статусы.Подготовлено)
Разберем наиболее универсальный и правильный подход с точки зрения стандартов разработки 1С. Если элемент справочника не является предопределенным, значение ссылочного типа необходимо передавать через параметр с помощью метода УстановитьПараметр().
Рассмотри пример кода на встроенном языке:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗаказПокупателя.Ссылка КАК Ссылка,
| ЗаказПокупателя.Статусы КАК Статусы,
| ЗаказПокупателя.Номенклатура КАК Номенклатура,
| ЗаказПокупателя.Количество КАК Количество
|ИЗ
| Документ.ЗаказПокупателя.Товары КАК ЗаказПокупателя
|ГДЕ
| ЗаказПокупателя.Ссылка.Проведен = ИСТИНА
| И ЗаказПокупателя.Статусы = &Статус";
Запрос.УстановитьПараметр("Статус", Справочники.Статусы.НайтиПоНаименованию("Подготовлено"));
Результат = Запрос.Выполнить();
Использование параметров позволяет СУБД кэшировать и повторно использовать план выполнения запроса, что существенно повышает быстродействие системы при частых обращениях.
Если требуется выполнить быстрый отбор без передачи параметра из кода, можно обратиться к реквизиту Наименование объекта через точку:
ВЫБРАТЬ
ЗаказПокупателя.Ссылка КАК Ссылка,
ЗаказПокупателя.Статусы КАК Статусы,
ЗаказПокупателя.Номенклатура КАК Номенклатура,
ЗаказПокупателя.Количество КАК Количество
ИЗ
Документ.ЗаказПокупателя.Товары КАК ЗаказПокупателя
ГДЕ
ЗаказПокупателя.Ссылка.Проведен = ИСТИНА
И ЗаказПокупателя.Статусы.Наименование = "Подготовлено"
Рассмотрим ситуацию, когда необходимо выбрать записи, соответствующие нескольким статусам одновременно (например, «Подготовлено» или «ВРаботе»).
Для этого можно использовать оператор В со списком строковых значений, что гораздо понятнее и эффективнее использования конструкции ИЛИ или шаблонов поиска:
ВЫБРАТЬ
ЗаказПокупателя.Ссылка КАК Ссылка,
ЗаказПокупателя.Статусы КАК Статусы,
ЗаказПокупателя.Номенклатура КАК Номенклатура,
ЗаказПокупателя.Количество КАК Количество
ИЗ
Документ.ЗаказПокупателя.Товары КАК ЗаказПокупателя
ГДЕ
ЗаказПокупателя.Ссылка.Проведен = ИСТИНА
И ЗаказПокупателя.Статусы.Наименование В ("Подготовлено", "ВРаботе")
Также возможен вариант проверки на вхождение подстроки через оператор ПОДОБНО:
ГДЕ
"ПодготовленоВРаботе" ПОДОБНО "%" + ЗаказПокупателя.Статусы.Наименование + "%"
Проанализируем потенциальные узкие места при выполнении подобного рода запросов:
ЗаказПокупателя.Ссылка.Проведен заставляет СУБД выполнять неявное левое соединение (LEFT JOIN) с таблицей шапки документа. Если обращаться к полям табличной части напрямую (например, ЗаказПокупателя.Статусы), лишних соединений не происходит.ПОДОБНО и процентом в начале строки: Шаблон вида "%Текст%" полностью блокирует использование индексов таблиц в СУБД, что приводит к полному сканированию таблицы (Full Table Scan).Перечисление. Это исключит проблему поиска по наименованию и ускорит выполнение запросов.