При разработке сложных отчетов или обработок в среде 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью динамического формирования текста запроса. В таких случаях параметры также устанавливаются программно, зачастую внутри циклов. Однако иногда возникает ситуация, когда после выполнения метода УстановитьПараметр() коллекция Запрос.Параметры остается пустой, а при выполнении самого запроса система выдает ошибку: "Значение параметра не задано". Разберем подробно причины такого поведения и выясним, как правильно работать с объектом Запрос.
Рассмотрим ситуацию на примере реального кода, который часто встречается в типовых конфигурациях или при доработке систем. Проблема заключается в том, что разработчик пытается передать имя параметра в метод точно так же, как оно написано в тексте самого запроса — с символом амперсанда (&).
Проанализируем фрагмент проблемного кода:
Запрос = Новый Запрос;
ТекстЗапроса = "";
СчетчикПараметров = 1;
Для Каждого ПланОбмена Из Метаданные.ПланыОбмена Цикл
// ... формирование текста запроса ...
ТекстЗапроса = ТекстЗапроса + "
|ИЗ
| ПланОбмена." + ПланОбмена.Имя + "
|ГДЕ
| Ссылка <> &ЭтотУзел" + СчетчикПараметров;
// ОШИБКА: использование "&" в имени параметра
Запрос.УстановитьПараметр("&ЭтотУзел" + СчетчикПараметров, ПланыОбмена[ПланОбмена.Имя].ЭтотУзел());
СчетчикПараметров = СчетчикПараметров + 1;
КонецЦикла;
В данном примере программист ожидает, что параметр будет добавлен в коллекцию. Однако платформа 1С воспринимает строку "&ЭтотУзел" как некорректное имя ключа для внутренней коллекции параметров. В результате значение не сопоставляется с текстом запроса, и при вызове метода Выполнить() система сообщает об отсутствии значения.
Для понимания причин ошибки важно различать две области применения имен параметров:
& является обязательным техническим маркером (префиксом). Он сообщает парсеру языка запросов 1С, что следующее за ним слово — это не имя поля таблицы или функции, а идентификатор, значение которого нужно извлечь из коллекции Параметры.Правильный вариант установки параметра:
// Верный способ: передаем имя без амперсанда
Запрос.УстановитьПараметр("ЭтотУзел" + СчетчикПараметров, СсылкаНаУзел);
Среди разработчиков часто возникают споры о том, что должно идти первым: присвоение текста свойству Запрос.Текст или вызов метода УстановитьПараметр(). Рассмотрим этот вопрос подробнее.
С точки зрения платформы 1С, коллекция Запрос.Параметры является независимой. Вы можете устанавливать параметры до того, как определите текст запроса. Это никак не повлияет на работоспособность кода. Однако для удобства чтения и отладки рекомендуется придерживаться одной из двух стратегий:
Проанализируем правильную реализацию динамического запроса:
Запрос = Новый Запрос;
ТекстЗапроса = "";
Счетчик = 1;
Для Каждого Строка Из ТаблицаУсловий Цикл
ИмяПараметра = "Парам" + Счетчик;
ТекстЗапроса = ТекстЗапроса + "ВЫБРАТЬ * ИЗ Справочник.Номенклатура ГДЕ Артикул = &" + ИмяПараметра;
// Устанавливаем параметр БЕЗ символа "&"
Запрос.УстановитьПараметр(ИмяПараметра, Строка.Артикул);
Счетчик = Счетчик + 1;
КонецЦикла;
Запрос.Текст = ТекстЗапроса;
Результат = Запрос.Выполнить();
Разберем несколько важных моментов, которые помогут избежать неочевидных ошибок:
1. Регистронезависимость имён. В языке запросов 1С параметры &ДатаНачала, &датаначала и &ДАТАНАЧАЛА считаются идентичными. То же самое относится и к методу УстановитьПараметр(). Если вы установите параметр с именем "Дата", а в запросе напишете &ДАТА, всё будет работать корректно.
2. Особенности отладки. Если вы просматриваете объект Запрос в отладчике, коллекция Параметры может выглядеть пустой, если вы допустили ошибку в имени (например, добавили лишний пробел или тот самый амперсанд). Платформа может не отображать ключи, которые она не смогла успешно проанализировать в контексте текущего текста запроса.
3. Очистка параметров. Важно помнить, что объект Запрос сохраняет параметры на протяжении всей своей "жизни". Если вы используете один и тот же объект для выполнения разных запросов в цикле, старые параметры никуда не исчезнут. У объекта нет метода Очистить() для параметров. Чтобы полностью сбросить состояние, лучше переинициализировать объект командой Запрос = Новый Запрос;.
4. Пакетные запросы. При использовании пакетов (когда в одном тексте несколько запросов разделены точкой с запятой), параметры являются общими для всего пакета. Нельзя задать разные значения для одного и того же имени &Дата в первом и втором запросе пакета.
Подводя итог, выделим правила, которые помогут сделать работу с запросами стабильной:
& в строковом параметре метода УстановитьПараметр().&Ссылка передана строка, запрос не выдаст ошибку при установке, но вернет пустой результат при выполнении.Соблюдение этих простых правил и понимание внутреннего устройства объекта Запрос позволит вам эффективно решать задачи любой сложности и быстро диагностировать ошибки в коде коллег или стандартных библиотек.