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