Разработка и Конфигурация · 11 мин
Как поместить таблицу значений в запрос в 1С
Как передать таблицу значений в запрос 1С через временную таблицу: МенеджерВременныхТаблиц, Поместить, типизация колонок, типичные ошибки и примеры кода.
Передача таблицы значений в запрос — одна из самых частых задач при разработке на платформе 1С:Предприятие. Такой приём нужен, когда данные для отбора или соединения получены программно: загружены из файла, рассчитаны алгоритмом, собраны из нескольких источников, и их нет в базе данных. Напрямую «подставить» таблицу в текст запроса нельзя — язык запросов работает только с таблицами информационной базы и временными таблицами.
Решение стандартное: таблица значений передаётся в запрос как параметр, а специальная конструкция языка запросов помещает её во временную таблицу. После этого временная таблица доступна в последующих пакетах запроса для соединений, отборов и группировок. Ниже разобран полный рабочий механизм, ограничения и типичные ошибки.
Как работает механизм временных таблиц в 1С
Запрос в 1С умеет читать данные только из таблиц информационной базы (справочников, документов, регистров) и из временных таблиц, созданных в рамках текущего запроса. Таблица значений — объект встроенного языка, в памяти сервера или клиента, и язык запросов её напрямую «не видит».
Мост между ними — параметр запроса. Если в тексте запроса написать ИЗ &ТЗ КАК ТЗ и установить параметру значение типа «ТаблицаЗначений», платформа на время выполнения запроса материализует эти данные как источник. Результат такого чтения помещают во временную таблицу конструкцией ПОМЕСТИТЬ.
Временные таблицы живут внутри объекта МенеджерВременныхТаблиц. Пока менеджер существует и запрос выполняется с ним, все временные таблицы, созданные в пакетах запроса, доступны последующим пакетам. После уничтожения менеджера временные таблицы удаляются автоматически.
Базовый пример: помещение таблицы значений в запрос
Минимальный рабочий сценарий состоит из четырёх шагов: создать менеджер временных таблиц, сформировать таблицу значений с типизированными колонками, написать пакетный запрос и выполнить его.
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст =
"ВЫБРАТЬ
| ТЗ.Номенклатура КАК Номенклатура,
| ТЗ.Количество КАК Количество
|ПОМЕСТИТЬ ВТ_Данные
|ИЗ
| &ТЗ КАК ТЗ
|;
|////////////////
|ВЫБРАТЬ
| ВТ.Номенклатура КАК Номенклатура,
| ВТ.Количество КАК Количество,
| Цены.Цена КАК Цена
|ИЗ
| ВТ_Данные КАК ВТ
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних() КАК Цены
| ПО ВТ.Номенклатура = Цены.Номенклатура";
Запрос.УстановитьПараметр("ТЗ", ТаблицаЗначений);
Результат = Запрос.Выполнить().Выгрузить();Обратите внимание на структуру текста: это пакетный запрос из двух пакетов, разделённых точкой с запятой. Первый пакет помещает параметр-таблицу во временную таблицу ВТ_Данные, второй читает её и соединяет с виртуальной таблицей регистра сведений. Оба пакета выполняются одним вызовом Выполнить(), поэтому менеджер временных таблиц общий и временная таблица доступна.
Если нужно получить именно результат второго пакета, используют Запрос.Выполнить() — он возвращает результат последнего пакета. Либо ВыполнитьПакет(), который возвращает массив результатов всех пакетов.
Почему обязательно типизировать колонки таблицы значений
Частая причина ошибки «Неверные параметры в операции сравнения» или пустого результата соединения — нетипизированные колонки. Если колонку добавить как ТЗ.Колонки.Добавить("Номенклатура") без типа, платформа не сможет корректно сопоставить её с полем базы данных при соединении.
Тип задают через объект ОписаниеТипов. Для ссылочных полей указывают конкретный тип ссылки, для строк — длину, для чисел — разрядность:
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
ТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", , , Новый КвалификаторыЧисла(15, 3)));
ТЗ.Колонки.Добавить("Комментарий", Новый ОписаниеТипов("Строка", , , , Новый КвалификаторыСтроки(100)));Если колонка может содержать ссылки разных справочников, допустим составной тип — перечислите типы через запятую в строке ОписаниеТипов. Но помните: соединение по составному полю с конкретным ссылочным полем базы может работать медленнее и требует аккуратного приведения типов через ВЫРАЗИТЬ.
Типичные сценарии использования
Отбор документов по списку ссылок
Когда есть программно сформированный список ссылок и нужно выбрать по ним данные, не всегда удобно использовать оператор В (&СписокСсылок) — при большом списке запрос с параметром-массивом может работать медленнее, чем соединение с временной таблицей. Поместите ссылки во временную таблицу и соедините её с таблицей документов.
Передача данных из загруженного файла
При загрузке из Excel или CSV данные сначала читаются в таблицу значений. Чтобы сопоставить строки файла с элементами базы (найти номенклатуру по артикулу, контрагента по ИНН), таблицу помещают в запрос и соединяют со справочниками. Это быстрее и надёжнее, чем цикл с поиском по каждой строке через НайтиПоРеквизиту.
Расчётные данные для отчёта
Если часть показателей вычислена алгоритмом (например, плановые значения, рассчитанные формулой), их помещают во временную таблицу и соединяют с фактическими данными из регистров. Так отчёт собирается одним запросом без постобработки выборки.
Как выбрать способ передачи данных
Работа с менеджером временных таблиц в нескольких запросах
Временная таблица не обязана использоваться только внутри одного пакетного запроса. Если несколько объектов Запрос используют один и тот же МенеджерВременныхТаблиц, временная таблица, созданная первым запросом, доступна второму и последующим. Это удобно при поэтапном построении сложной выборки.
Для отладки содержимое временной таблицы можно выгрузить в таблицу значений: Запрос.МенеджерВременныхТаблиц.Таблицы["ВТ_Данные"].ПолучитьДанные().Выгрузить(). Это позволяет проверить, что данные из параметра попали во временную таблицу корректно, до того как строить основной запрос.
Если временная таблица больше не нужна, её можно удалить явно пакетом УНИЧТОЖИТЬ ВТ_Данные — это освобождает память сервера СУБД, что важно при работе с крупными наборами данных в длинных алгоритмах.
Типичные ошибки и способы их избежать
Отдельная группа проблем — попытка передать в параметр не таблицу значений, а, например, результат запроса или табличную часть. Табличную часть документа нужно предварительно выгрузить: ТЗ = Документ.Товары.Выгрузить(). Результат запроса — тоже выгрузить в таблицу значений через .Выгрузить().
Проверка результата и ограничения
После выполнения запроса убедитесь, что количество строк результата соответствует ожиданиям. При левом соединении число строк не должно быть меньше числа строк исходной таблицы значений (если нет дублей по ключу соединения, которые, наоборот, увеличат результат). Резкий рост числа строк — признак дублирования ключей в соединяемой таблице.
Как проверить результат
Совпадает с числом строк ТЗ или больше при известных дублях ключа
Меньше числа строк ТЗ при левом соединении — данные потеряны
Поля заполнены ссылочными значениями ожидаемого типа
NULL в полях — типы колонок не совпали или ключи не найдены
Все строки и колонки из исходной ТЗ на месте
Пусто или часть колонок отсутствует — ошибка в тексте первого пакета
По производительности: передача таблицы параметром и создание временной таблицы — это физическая вставка строк во временное хранилище СУБД. Для таблиц в тысячи строк это работает быстро, но при десятках и сотнях тысяч строк стоит замерить время и рассмотреть альтернативы: пакетную обработку порциями или запись в служебный регистр сведений с последующим соединением.
Что важно запомнить
Таблица значений попадает в запрос через параметр и конструкцию ПОМЕСТИТЬ во временную таблицу. Обязательны: типизированные колонки, общий МенеджерВременныхТаблиц для всех пакетов и запросов, установка параметра до выполнения. Результат проверяйте по числу строк и выгрузке временной таблицы.
Частые вопросы
Можно ли передать таблицу значений в запрос без временной таблицы?
Да, но только для отбора: параметр-таблицу можно использовать с оператором В, например ГДЕ (Номенклатура, Склад) В (ВЫБРАТЬ Т.Номенклатура, Т.Склад ИЗ &ТЗ КАК Т). Однако для соединений и многократного использования данных временная таблица удобнее и обычно производительнее.
Почему возникает ошибка «Таблица не найдена: ВТ_Данные»?
Запрос, который обращается к временной таблице, выполняется без менеджера временных таблиц или с другим менеджером. Присвойте обоим запросам один и тот же объект МенеджерВременныхТаблиц и убедитесь, что первый запрос (создающий таблицу) выполнен раньше.
Как передать в запрос табличную часть документа?
Сначала выгрузите табличную часть в таблицу значений: ТЗ = ДокументОбъект.Товары.Выгрузить(). Затем передайте её как обычную таблицу значений через параметр. При необходимости оставьте только нужные колонки через Выгрузить(,"Номенклатура,Количество").
Что делать, если колонка содержит значения разных типов?
Задайте составной тип в ОписаниеТипов, перечислив допустимые типы. В запросе при соединении с конкретным ссылочным полем приведите значение через ВЫРАЗИТЬ(ТЗ.Поле КАК Справочник.Номенклатура), иначе соединение может не сработать.
Нужно ли уничтожать временные таблицы вручную?
Не обязательно: при уничтожении менеджера временных таблиц все его таблицы удаляются автоматически. Явное УНИЧТОЖИТЬ оправдано в длинных процедурах с большими таблицами, чтобы раньше освободить ресурсы сервера СУБД.
Можно ли использовать этот приём в запросе динамического списка или СКД?
В динамическом списке произвольные временные таблицы из параметров-таблиц не поддерживаются. В СКД таблицу значений подключают иначе — через набор данных «Объект» с передачей внешних данных в процедуре ПриКомпоновкеРезультата, а не через параметр запроса.