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