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