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