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