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