К статье
Практический материал

Разработка и Конфигурация · 11 мин

Временная таблица в 1С: как создать и использовать в запросах

Как сделать временную таблицу в запросе 1С: синтаксис ПОМЕСТИТЬ, менеджер временных таблиц, индексы, типичные ошибки и примеры кода для разработчика.

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

Типовые сценарии применения: отбор товаров по списку из таблицы значений, предварительная фильтрация регистра перед соединением, расчёт промежуточных итогов, передача данных между несколькими запросами. Без временных таблиц такие задачи решаются вложенными запросами, которые тяжелее читать и часто медленнее выполняются.

Работа с временными таблицами доступна на любом современном релизе платформы 1С:Предприятие 8 и не зависит от конкретной конфигурации — синтаксис одинаков в «Управлении торговлей», «Бухгалтерии», «Зарплате и управлении персоналом» и самописных решениях.

Что такое временная таблица и когда она нужна

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

Временная таблица оправдана, когда одни и те же отобранные данные нужны несколько раз, когда в запрос передаётся список значений из кода (массив, таблица значений), когда сложный запрос нужно разбить на понятные этапы или когда соединение «в лоб» с большим регистром работает медленно и требуется сначала сузить выборку.

Временная таблица не нужна, если задача решается одним простым запросом без повторного использования промежуточных данных. Избыточное применение временных таблиц тоже вредно: каждая операция ПОМЕСТИТЬ — это материализация данных, которая расходует память и время.

Как создать временную таблицу конструкцией ПОМЕСТИТЬ

Базовый способ — предложение ПОМЕСТИТЬ в тексте запроса. Результат выборки сохраняется под указанным именем, и дальше в пакетном запросе к нему можно обращаться по этому имени. Запросы в пакете разделяются точкой с запятой.

ВЫБРАТЬ

Номенклатура.Ссылка КАК Товар,

Номенклатура.Код КАК Код

ПОМЕСТИТЬ ВТ_ОтборТоваров

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

Номенклатура.Родитель = &Группа

;

ВЫБРАТЬ

Остатки.Номенклатура КАК Товар,

Остатки.КоличествоОстаток КАК Остаток

ИЗ

РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки

ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ОтборТоваров КАК Отбор

ПО Остатки.Номенклатура = Отбор.Товар

В примере сначала формируется список товаров нужной группы, затем он соединяется с виртуальной таблицей остатков. Такой подход читается проще, чем вложенный запрос, и позволяет использовать ВТ_ОтборТоваров повторно в других частях пакета.

Имя временной таблицы должно быть уникально в пределах пакета или менеджера. Повторное ПОМЕСТИТЬ в таблицу с тем же именем вызовет ошибку — сначала таблицу нужно уничтожить.

Как передать данные из кода через менеджер временных таблиц

Вторая частая задача — отфильтровать запрос по списку, который сформирован в коде: массивом ссылок или таблицей значений. Для этого объект Запрос связывается с объектом МенеджерВременныхТаблиц, а таблица значений помещается во временную таблицу первым запросом пакета.

Запрос = Новый Запрос;

Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;

Запрос.УстановитьПараметр("ТаблицаТоваров", ТаблицаЗначений);

Запрос.Текст =

"ВЫБРАТЬ

| Таблица.Товар КАК Товар,

| Таблица.Количество КАК Количество

|ПОМЕСТИТЬ ВТ_Товары

|ИЗ

| &ТаблицаТоваров КАК Таблица

|;

|

|ВЫБРАТЬ

| ..."

;

Результат = Запрос.Выполнить().Выбрать();

Таблица значений, передаваемая параметром, должна иметь типизированные колонки — типы определяются по содержимому. Если колонка содержит значения разных типов, в запросе могут возникнуть проблемы с соединениями и сравнениями, поэтому таблицу лучше готовить аккуратно, с явным описанием колонок через ОписаниеТипов.

Преимущество менеджера временных таблиц в том, что созданные таблицы доступны нескольким последовательным запросам. Можно выполнить один запрос с ПОМЕСТИТЬ, затем создать второй объект Запрос с тем же менеджером и использовать таблицу без повторного заполнения.

Порядок создания временной таблицы из кода
  1. 1
    Создайте объект Запрос и присвойте ему Новый МенеджерВременныхТаблиц
  2. 2
    Передайте таблицу значений параметром через УстановитьПараметр
  3. 3
    В первом запросе пакета выберите данные из параметра с ПОМЕСТИТЬ ВТ_Имя
  4. 4
    В последующих запросах пакета обращайтесь к ВТ_Имя как к обычной таблице
  5. 5
    Выполните запрос и проверьте результат через Выбрать() или Выгрузить()

Индексирование и производительность

По умолчанию временная таблица не имеет индексов, и соединение с ней большой выборки может выполняться полным перебором. Если временная таблица участвует в соединении или отборе по конкретным полям, добавьте предложение ИНДЕКСИРОВАТЬ ПО.

ВЫБРАТЬ

Номенклатура.Ссылка КАК Товар

ПОМЕСТИТЬ ВТ_Товары

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

Номенклатура.Родитель = &Группа

ИНДЕКСИРОВАТЬ ПО

Товар

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

Ещё одно правило производительности: помещайте во временную таблицу только нужные поля и строки. Конструкция «ВЫБРАТЬ * ПОМЕСТИТЬ» по широкому регистру создаст в памяти лишнюю копию данных. Чем уже и короче временная таблица, тем дешевле с ней работать.

Если запрос с временной таблицей работает медленно, первым делом проверьте, есть ли индекс по полям соединения, и не тащите ли вы в ПОМЕСТИТЬ лишние поля. Эти две причины покрывают большинство проблем с производительностью.
ПЗ
Практическое замечание

Удаление временных таблиц и управление памятью

Временная таблица занимает память сервера, пока существует менеджер временных таблиц или пока не выполнена команда УНИЧТОЖИТЬ. В длинных пакетных запросах и при многократных вызовах в цикле это может привести к заметному росту потребления памяти.

УНИЧТОЖИТЬ ВТ_Товары

Рекомендуется уничтожать временную таблицу сразу после того, как она использована в последний раз, если пакет продолжает выполняться. Это особенно актуально в серверных процедурах, которые вызываются массово — например, при обработке больших документов или в фоновых заданиях.

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

Типичные ошибки при работе с временными таблицами

Первая распространённая ошибка — обращение к временной таблице из другого запроса, у которого не задан тот же менеджер временных таблиц. Платформа сообщит, что таблица не найдена. Решение: присвоить обоим запросам один объект МенеджерВременныхТаблиц.

Вторая ошибка — повторное ПОМЕСТИТЬ в таблицу с тем же именем без предварительного УНИЧТОЖИТЬ. Третья — использование поля временной таблицы в соединении без индекса при большом объёме данных, из-за чего запрос «зависает». Четвёртая — передача в параметр таблицы значений с незаполненными или смешанными типами колонок, что ломает сравнения.

Типичные ошибки
01
Обращение к временной таблице из запроса без общего менеджера — ошибка «Таблица не найдена»
02
Повторное ПОМЕСТИТЬ в существующее имя без УНИЧТОЖИТЬ — ошибка выполнения запроса
03
Отсутствие ИНДЕКСИРОВАТЬ ПО по полям соединения — резкое падение скорости на больших данных
04
Помещение в таблицу всех полей регистра вместо нужных — лишний расход памяти
05
Неявное приведение типов при передаче таблицы значений — пустые соединения без видимой ошибки

Отладить содержимое временной таблицы можно простым приёмом: временно заменить итоговый запрос на «ВЫБРАТЬ * ИЗ ВТ_Имя» и выгрузить результат в таблицу значений. Это позволяет убедиться, что промежуточные данные сформированы так, как ожидалось.

Альтернативы временным таблицам

Не всегда временная таблица — единственный вариант. Вложенный запрос подходит, когда промежуточные данные нужны один раз и логика простая. Параметр-массив с условием «В (&Список)» заменяет временную таблицу, если передаётся простой список ссылок без дополнительных полей. Пакетный запрос без временных таблиц подходит для нескольких независимых выборок.

Сравнение вариантов

Временная таблица

Нужна при повторном использовании данных, передаче таблиц значений и сложных многоэтапных выборках; требует контроля памяти

Вложенный запрос

Подходит для разового отбора; проще синтаксис, но хуже читаемость при глубокой вложенности

Параметр-массив с условием В

Оптимален для простого списка ссылок; не подходит, если к каждому элементу нужны дополнительные поля

Пакетный запрос

Для независимых выборок одним обращением к базе; не решает задачу переиспользования данных

Как проверить результат

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

Контрольные точки

Как проверить результат

Выполнение запроса
Норма

Запрос выполняется без ошибок, временная таблица доступна в последующих частях пакета

Тревожный признак

Ошибка «Таблица не найдена» или «Таблица уже существует»

Содержимое таблицы
Норма

Выборка из ВТ возвращает ожидаемые строки и типы полей

Тревожный признак

Пустой результат или NULL в полях соединения

Скорость выполнения
Норма

Запрос отрабатывает за время, приемлемое для пользователя

Тревожный признак

Резкий рост времени при увеличении объёма данных — вероятно, нет индекса

Частые вопросы

Чем временная таблица отличается от таблицы значений?

Таблица значений — объект встроенного языка, живущий в коде и недоступный напрямую в запросе. Временная таблица существует внутри запроса или менеджера временных таблиц и участвует в соединениях на стороне СУБД. Таблицу значений можно передать в запрос параметром и превратить во временную таблицу через ПОМЕСТИТЬ.

Можно ли использовать временную таблицу в другом запросе?

Да, если обоим запросам назначен один и тот же объект МенеджерВременныхТаблиц. Без общего менеджера таблица существует только внутри одного пакетного запроса и недоступна извне.

Как посмотреть содержимое временной таблицы при отладке?

Временно добавьте в конец пакета запрос «ВЫБРАТЬ * ИЗ ВТ_Имя» и выгрузите результат методом Выгрузить(). В консоли запросов на управляемых формах многие инструменты также показывают список временных таблиц пакета.

Нужно ли всегда писать ИНДЕКСИРОВАТЬ ПО?

Нет. Индекс оправдан, когда временная таблица участвует в соединениях или отборах по конкретным полям и содержит заметное число строк. Для маленькой таблицы на несколько десятков записей индекс не даст выигрыша.

Что происходит с временными таблицами после выполнения запроса?

Если менеджер временных таблиц не задан явно, таблицы уничтожаются автоматически после выполнения пакета. При явном менеджере они живут до вызова метода Закрыть() или до уничтожения менеджера, поэтому в длительных операциях таблицы стоит удалять командой УНИЧТОЖИТЬ.

Можно ли создать временную таблицу в СКД?

В схеме компоновки данных набор данных «Запрос» поддерживает пакетные запросы, включая ПОМЕСТИТЬ, — итоговым должен быть последний запрос пакета. Альтернатива — набор данных «Объект» с передачей готовой таблицы значений из кода.

Итог

Что важно запомнить

Временная таблица создаётся конструкцией ПОМЕСТИТЬ, передача данных из кода выполняется через МенеджерВременныхТаблиц, соединения ускоряются предложением ИНДЕКСИРОВАТЬ ПО, а после использования таблицу следует удалить командой УНИЧТОЖИТЬ. Проверяйте запросы на реальном объёме данных и не помещайте в таблицу лишние поля.