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

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

Как создать временную таблицу в 1С

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

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

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

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

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

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

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

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

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

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

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

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

"ВЫБРАТЬ

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

| Товары.Наименование КАК Наименование

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

|ИЗ

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

|ГДЕ

| НЕ Товары.ПометкаУдаления

|;

|

|ВЫБРАТЬ

| ВТ_Товары.Номенклатура,

| ВТ_Товары.Наименование

|ИЗ

| ВТ_Товары КАК ВТ_Товары";

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

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

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

Менеджер временных таблиц: зачем нужен и как настроить

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

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

ЗапросПодготовка = Новый Запрос;

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

ЗапросПодготовка.Текст =

"ВЫБРАТЬ

| Продажи.Номенклатура КАК Номенклатура,

| СУММА(Продажи.КоличествоОборот) КАК Количество

|ПОМЕСТИТЬ ВТ_Продажи

|ИЗ

| РегистрНакопления.Продажи.Обороты(&Начало, &Конец, , ) КАК Продажи

|СГРУППИРОВАТЬ ПО

| Продажи.Номенклатура";

ЗапросПодготовка.УстановитьПараметр("Начало", НачалоПериода);

ЗапросПодготовка.УстановитьПараметр("Конец", КонецПериода);

ЗапросПодготовка.Выполнить();

ЗапросЧтение = Новый Запрос;

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

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

"ВЫБРАТЬ

| ВТ_Продажи.Номенклатура,

| ВТ_Продажи.Количество

|ИЗ

| ВТ_Продажи КАК ВТ_Продажи";

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

Оба запроса ссылаются на один и тот же объект МенеджерВТ, поэтому второй видит таблицу, созданную первым. Пока переменная менеджера доступна и не уничтожена, временные таблицы в нём живут. Это удобно для поэтапной отладки: можно выполнять запросы по одному и проверять промежуточные результаты.

Если назначить второму запросу новый менеджер или не назначить вовсе, обращение к ВТ_Продажи завершится ошибкой «Таблица не найдена». Это самая частая причина проблем у начинающих разработчиков при работе с временными таблицами.

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

Как передать таблицу значений во временную таблицу

Частая задача — передать в запрос данные, которых нет в базе: список контрагентов из обработки, загруженный прайс, произвольные отборы. Для этого таблица значений передаётся как параметр запроса, а в тексте описывается её структура через конструкцию выборки из параметра.

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

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

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

"ВЫБРАТЬ

| ВнешниеДанные.Код КАК Код,

| ВнешниеДанные.Цена КАК Цена

|ПОМЕСТИТЬ ВТ_Прайс

|ИЗ

| &ТаблицаПрайса КАК ВнешниеДанные";

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

Запрос.Выполнить();

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

Передача большой таблицы значений в параметр — ресурсоёмкая операция: данные сериализуются и загружаются на СУБД. Если строк десятки тысяч и больше, оцените, нельзя ли получить те же данные запросом напрямую из базы или ограничить состав колонок только действительно нужными.

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

Использование временных таблиц в консоли запросов и СКД

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

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

При переносе текста из консоли в модуль проверьте, что все параметры установлены до вызова Выполнить(), а символы переноса строк корректно оформлены вертикальной чертой — консоль часто хранит текст без этого форматирования.

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

Производительность и ограничения

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

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

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

Проверка результата и отладка

Самый надёжный способ убедиться, что временная таблица создана корректно, — выполнить в том же менеджере контрольный запрос ВЫБРАТЬ * ИЗ ВТ_Имя и посмотреть результат. В отладчике это делается отдельным объектом запроса с тем же менеджером временных таблиц.

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

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

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

Число строк во временной таблице
Норма

Совпадает с ожидаемым количеством после отборов

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

Строк сильно больше или меньше — проверьте условия ГДЕ и соединения

Поля соединений
Норма

Заполнены, типы совпадают с соединяемыми таблицами

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

NULL или несовпадение типов — соединение даст пустой или неполный результат

Время выполнения пакета
Норма

Сопоставимо с обычными запросами к тем же данным

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

Кратный рост времени — проверьте индексацию и объём помещаемых данных

Часто задаваемые вопросы

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

Да, если она создаётся и используется внутри одного текста запроса (одного пакета). Платформа создаст менеджер неявно. Явный МенеджерВременныхТаблиц нужен только когда таблица должна быть доступна нескольким отдельным объектам Запрос.

Как удалить временную таблицу?

Запросом с текстом «УНИЧТОЖИТЬ ИмяТаблицы», выполненным в том же менеджере. Если менеджер больше не нужен целиком, достаточно освободить переменную — все его таблицы будут удалены автоматически.

Почему запрос выдаёт ошибку «Таблица не найдена»?

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

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

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

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

Зависит от сценария. Если промежуточный результат используется один раз, вложенный запрос обычно предпочтительнее — СУБД сама оптимизирует план. Временная таблица выигрывает, когда результат нужен несколько раз или когда её индексация ускоряет соединения на больших объёмах.

Сохраняется ли временная таблица между вызовами сервера?

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

Итог

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

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