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