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