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

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

Как обработать таблицу значений в запросе 1С

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

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

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

Когда таблицу значений передают в запрос

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

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

Подготовка таблицы значений: типы колонок и состав данных

Главное требование на этапе подготовки — у каждой колонки таблицы значений должен быть явно задан тип через ОписаниеТипов. Если колонка создаётся без типа или тип определяется неявно по первому значению, запрос может не построиться либо выдаст ошибку о невозможности определить тип поля временной таблицы.

Для ссылочных колонок указывайте конкретный тип, например Новый ОписаниеТипов("СправочникСсылка.Номенклатура"). Составной тип (несколько видов ссылок) допустим, но замедляет соединения и может ломать планы запросов — по возможности ограничивайте колонку одним типом. Числовые и строковые колонки тоже лучше задавать с точной длиной и точностью, чтобы типы во временной таблице совпадали с типами полей базы при соединении.

Перед передачей в запрос полезно свернуть таблицу методом Свернуть() или удалить явные дубли: лишние строки увеличивают временную таблицу и могут задвоить результат соединения.

Базовый код: параметр, ПОМЕСТИТЬ и менеджер временных таблиц

Минимальный рабочий пример передачи таблицы значений в запрос выглядит так:

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

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

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

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

"ВЫБРАТЬ

| ТЗ.Номенклатура КАК Номенклатура,

| ТЗ.Количество КАК Количество

|ПОМЕСТИТЬ ВТ_Данные

|ИЗ

| &ТЗ КАК ТЗ";

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

После выполнения этого пакета временная таблица ВТ_Данные живёт в менеджере временных таблиц и доступна следующим запросам. Важно: параметр-таблица указывается в источнике ИЗ &ТЗ КАК ТЗ, а не в секции выбора — это частая синтаксическая ошибка новичков.

Менеджер временных таблиц создаётся один раз и назначается каждому запросу, который должен видеть ВТ_Данные. Если создать новый менеджер для второго запроса, временная таблица «потеряется» — запрос завершится ошибкой «Таблица не найдена».

Порядок действий
  1. 1
    Создайте таблицу значений и задайте типы всех колонок через ОписаниеТипов
  2. 2
    Заполните таблицу данными, при необходимости сверните дубли
  3. 3
    Создайте запрос, назначьте ему Новый МенеджерВременныхТаблиц
  4. 4
    Установите параметр с таблицей и выполните пакет с ПОМЕСТИТЬ ВТ_Данные
  5. 5
    В следующем запросе с тем же менеджером соедините ВТ_Данные с таблицами базы
  6. 6
    Проверьте результат выборкой или выгрузкой в таблицу значений

Соединение временной таблицы с данными базы

Основная ценность приёма — соединение переданных данных с учётными. Типовой запрос получает остатки или цены только по списку номенклатуры из таблицы значений:

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

"ВЫБРАТЬ

| ВТ.Номенклатура КАК Номенклатура,

| ВТ.Количество КАК Количество,

| ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток

|ИЗ

| ВТ_Данные КАК ВТ

| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки

| ПО ВТ.Номенклатура = Остатки.Номенклатура";

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

Несколько практических правил для таких соединений. Во-первых, используйте ЛЕВОЕ СОЕДИНЕНИЕ, если нужны все строки исходной таблицы даже при отсутствии данных в регистре, и оборачивайте поля правой таблицы в ЕСТЬNULL(). Во-вторых, поле связи во временной таблице и в таблице базы должны совпадать по типу — иначе СУБД может не использовать индекс, и запрос резко замедлится. В-третьих, виртуальные таблицы регистров выбирайте с параметрами отбора, а не фильтруйте условием ГДЕ после соединения.

Если временная таблица нужна только как фильтр «взять документы из списка», достаточно условия ГДЕ Документ.Ссылка В (ВЫБРАТЬ ВТ.Ссылка ИЗ ВТ_Данные КАК ВТ) — без явного соединения.

Если соединение с регистром работает медленно даже на небольшой таблице значений, проверьте тип колонки связи: составной тип вроде «СправочникСсылка.Номенклатура, СправочникСсылка.Характеристики» часто мешает оптимизатору. Сузьте колонку до одного типа — эффект обычно заметен сразу.
ПЗ
Практическое замечание

Несколько таблиц значений и дальнейшая обработка

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

Запрос.УстановитьПараметр("Товары", ТЗТовары);

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

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

"ВЫБРАТЬ Т.Номенклатура ПОМЕСТИТЬ ВТ_Товары ИЗ &Товары КАК Т

|;

|ВЫБРАТЬ С.Склад ПОМЕСТИТЬ ВТ_Склады ИЗ &Склады КАК С";

Дальше временные таблицы можно обрабатывать как любые источники: группировать (СГРУППИРОВАТЬ ПО), рассчитывать итоги, накладывать условия, соединять друг с другом. Результат финального запроса выгружается методом Выгрузить() обратно в таблицу значений — уже с подтянутыми из базы полями.

Когда временные таблицы больше не нужны, их стоит удалить конструкцией УНИЧТОЖИТЬ ВТ_Данные или закрытием менеджера временных таблиц — это освобождает ресурсы сервера СУБД, особенно в длительных обработках с циклами.

Типичные ошибки и как их диагностировать

Типичные ошибки
01
Колонка без типа или с пустыми значениями — запрос падает с ошибкой определения типа поля временной таблицы; задайте ОписаниеТипов явно
02
Новый менеджер временных таблиц для второго запроса — ошибка «Таблица не найдена: ВТ_Данные»; используйте один менеджер на всю цепочку
03
Параметр-таблица в секции ВЫБРАТЬ вместо ИЗ — синтаксическая ошибка; таблица указывается как источник ИЗ &ТЗ
04
Дубли строк в исходной таблице — задвоение результата после соединения; сверните таблицу перед передачей
05
Несовпадение типов полей связи — соединение без индекса и таймауты; приведите типы колонок к типам полей базы

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

Ещё одна ловушка — имена колонок с точками или спецсимволами. Если колонка таблицы значений названа, например, «Номенклатура.Ссылка», обращение к ней в запросе потребует экранирования и создаст путаницу. Используйте простые имена из букв и цифр.

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

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

Выполнение пакета с ПОМЕСТИТЬ
Норма

Запрос выполняется без ошибок, временная таблица создана

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

Ошибка о типе поля или синтаксисе — проверьте типы колонок и расположение параметра

Доступность ВТ во втором запросе
Норма

Соединение с ВТ_Данные возвращает строки

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

«Таблица не найдена» — менеджер временных таблиц разный

Количество строк результата
Норма

Совпадает с числом строк исходной таблицы при левом соединении

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

Строк больше — дубли в источнике или множественные связи

Альтернативы: когда таблица значений не нужна

Не каждая задача требует передачи таблицы в запрос. Если список значений небольшой и однотипный (например, десять ссылок), достаточно параметра-массива или списка значений с условием В (&Список) — это проще и не создаёт временную таблицу.

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

Сравнение вариантов

Параметр-массив с условием В (&Список)

Подходит для простого отбора по одному полю и небольшого списка; не позволяет передать несколько связанных колонок

Таблица значений + временная таблица

Универсальный вариант для мультиколоночных внешних данных и соединений; требует типизации и расходует ресурсы СУБД

Промежуточный регистр сведений

Оправдан при регулярной загрузке больших объёмов; требует изменения конфигурации и регламентов очистки

Отладка: как посмотреть содержимое временной таблицы

При отладке удобно проверить, что реально попало во временную таблицу. Для этого выполняется служебный запрос ВЫБРАТЬ * ИЗ ВТ_Данные с тем же менеджером временных таблиц, а результат выгружается и просматривается. В конфигураторе это делается через точку останова и вычисление выражения Запрос.Выполнить().Выгрузить() после подмены текста запроса.

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

Итог

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

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

Частые вопросы

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

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

Почему запрос выдаёт ошибку «Невозможно определить тип поля»?

Причина почти всегда в колонке таблицы значений без заданного типа или в колонке, заполненной только значениями Неопределено. Задайте тип каждой колонки через ОписаниеТипов при создании таблицы и убедитесь, что в данных нет полностью пустых колонок.

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

Установите два параметра, например &Товары и &Склады, и поместите каждый в свою временную таблицу двумя пакетами одного запроса. Дальше обе временные таблицы доступны для соединений в последующих пакетах при условии общего менеджера временных таблиц.

Что быстрее: таблица значений в запросе или обход в цикле с запросами?

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

Нужно ли уничтожать временные таблицы после использования?

Желательно, особенно в длительных обработках и циклах: команда УНИЧТОЖИТЬ освобождает ресурсы сервера СУБД сразу, а не в момент закрытия менеджера. В коротких разовых операциях можно положиться на автоматическое освобождение при выходе менеджера из области видимости.

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

Язык запросов 1С предназначен для чтения данных и не выполняет запись. Таблица значений в запросе используется только для отбора и соединений. Изменение данных выполняется отдельно — через объекты (запись документов, наборы записей регистров) на основании полученной выборки.