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