Как правильно передать данные табличной части в запрос во внешней обработке 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке внешних обработок в системе 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью обработки данных, которые пользователь ввел в таблицу на форме, с помощью языка запросов. Однако простая передача табличной части в качестве параметра запроса часто вызывает ошибку "Неверные параметры". В этой статье мы подробно разберем, почему это происходит и как правильно организовать работу с временными таблицами на сервере.

Анализируем причину ошибки

Рассмотрим ситуацию, с которой столкнулся автор темы. В модуле управляемой формы внешней обработки написан код, который пытается поместить данные из объекта Объект.ПроизвольныеСтроки во временную таблицу запроса. При выполнении метода Запрос.Выполнить() система выдает ошибку. Проанализируем исходный код:


&НаСервере
Процедура ПоискПодстрокВТЧ()
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
                    |    ВрТаб.НомерСтроки КАК НомерСтроки,
                    |    ВрТаб.Значение КАК Значение
                    |ПОМЕСТИТЬ ВТ
                    |ИЗ
                    |    &ТабичнаяЧасть КАК ВрТаб";  
    
    Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
    Запрос.УстановитьПараметр("ТабичнаяЧасть", Объект.ПроизвольныеСтроки);
    Запрос.Выполнить();
 КонецПроцедуры

Основная причина ошибки кроется в специфике работы управляемых форм. Объект Объект.ПроизвольныеСтроки в контексте модуля формы имеет тип ДанныеФормыКоллекция. Несмотря на то, что визуально и функционально эта коллекция похожа на таблицу, механизм запросов 1С не умеет работать с этим типом данных напрямую. Запрос ожидает получить либо ссылку на таблицу в базе данных, либо объект типа ТаблицаЗначений.

Решение проблемы: метод Выгрузить()

Для того чтобы запрос смог обработать данные из коллекции формы, их необходимо преобразовать в «понятную» для него структуру. Самый простой и эффективный способ — использовать метод Выгрузить(). Этот метод создает копию данных коллекции в виде объекта ТаблицаЗначений, который находится в оперативной памяти сервера.

Исправленная строка установки параметра будет выглядеть так:


Запрос.УстановитьПараметр("ТабичнаяЧасть", Объект.ПроизвольныеСтроки.Выгрузить());

Важное замечание: в коде автора также присутствует опечатка в имени параметра — ТабичнаяЧасть. Хотя система позволяет использовать любые имена переменных, рекомендуется придерживаться правил русского языка (ТабличнаяЧасть), чтобы избежать путаницы при дальнейшем сопровождении кода.

Разберем нюансы работы с временными таблицами

Посмотрим на процесс глубже. Когда мы передаем таблицу значений в запрос, мы обязательно должны использовать конструкцию ПОМЕСТИТЬ. Это связано с тем, что данные из оперативной памяти (наша выгруженная таблица) должны быть переданы на сторону СУБД (SQL) или во внутренний менеджер временных таблиц 1С. Без создания временной таблицы выбрать данные из параметра-таблицы невозможно.

Рассмотрим по шагам, что происходит в коде:

  1. Создание менеджера временных таблиц: Строка Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц; необходима, если вы планируете использовать созданную таблицу ВТ в других запросах в рамках этой же процедуры. Если же вы выполняете один пакетный запрос, менеджер можно не создавать явно — 1С создаст его автоматически.
  2. Типизация колонок: При выгрузке данных через Выгрузить() важно, чтобы колонки в таблице на форме имели четко определенные типы. Если тип колонки не определен (составной или «Любая ссылка»), запрос может работать некорректно или медленно.
  3. Индексация: Если в вашей табличной части много строк (например, более 1000), для ускорения последующих соединений с этой временной таблицей следует добавить индексацию.

Проанализируем пример с индексацией:


Запрос.Текст = "ВЫБРАТЬ
                |    ВрТаб.НомерСтроки КАК НомерСтроки,
                |    ВрТаб.Значение КАК Значение
                |ПОМЕСТИТЬ ВТ
                |ИЗ
                |    &ТабличнаяЧасть КАК ВрТаб
                |ИНДЕКСИРОВАТЬ ПО
                |    Значение";

Альтернативные подходы

Выясним, всегда ли нужно использовать метод Выгрузить(). На самом деле, это зависит от того, сохранены ли данные в базе данных:

  1. Данные еще не записаны: Если пользователь только что ввел строки в обработку и еще не нажал кнопку «Сохранить» или «Выполнить», то метод с Выгрузить() является единственно возможным, так как данных в физических таблицах СУБД еще нет.
  2. Данные уже в базе: Если мы работаем с табличной частью существующего документа, эффективнее будет не передавать таблицу параметром, а обратиться к ней напрямую через запрос к базе данных.

Сравним пример прямого обращения (более производительный способ для больших объемов данных):


Запрос.Текст = "ВЫБРАТЬ
                |    ТЧ.НомерСтроки,
                |    ТЧ.Значение
                |ИЗ
                |    Документ.МойДокумент.ПроизвольныеСтроки КАК ТЧ
                |ГДЕ
                |    ТЧ.Ссылка = &СсылкаДокумента";
Запрос.УстановитьПараметр("СсылкаДокумента", Объект.Ссылка);

Однако в контексте внешних обработок чаще всего используется именно первый вариант с передачей таблицы значений, так как обработки зачастую предназначены для манипуляции временными данными «на лету».

Рекомендации по форматированию и безопасности

При работе с внешними источниками данных в запросах помните о следующих правилах:

Таким образом, мы выяснили, что основной ошибкой было несоответствие типов данных. Использование метода Выгрузить() преобразует коллекцию формы в полноценную ТаблицаЗначений, что позволяет успешно использовать её в любом SQL-запросе в рамках платформы 1С.

← На главную