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

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

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

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

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

Такой приём нужен в типовых задачах: отобрать документы по списку, сформированному вне запроса; подставить в отчёт данные, рассчитанные алгоритмом; сопоставить загруженный из Excel прайс с номенклатурой базы. Без временной таблицы пришлось бы перебирать строки в цикле и выполнять десятки отдельных запросов, что заметно медленнее.

Ниже разобран полный рабочий сценарий: подготовка таблицы значений, передача её в запрос, создание временной таблицы, соединение с данными базы, а также типичные ошибки и ограничения метода.

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

Механизм оправдан, когда источник данных — не база. Например, вы загрузили файл с артикулами поставщика и хотите одним запросом найти соответствия в справочнике «Номенклатура». Или алгоритм рассчитал список контрагентов с особыми условиями, и по этому списку нужно выбрать документы.

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

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

Маршрут решения

Как выбрать подход

Данные получены из файла, формы или расчёта в кодеПередавайте таблицу значений параметром и создавайте временную таблицу
Данные уже есть в регистре или справочникеПишите запрос напрямую к таблицам базы, таблица значений не нужна
Нужно отобрать по короткому списку значений (до нескольких десятков)Достаточно условия В (&Список) с массивом — без временной таблицы

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

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

Рекомендуется задавать типы через ОписаниеТипов. Для ссылочных полей указывайте конкретный тип ссылки, а не составной «любая ссылка» — это упрощает соединение и позволяет обращаться к реквизитам через точку.

ТаблицаАртикулов = Новый ТаблицаЗначений;

ТаблицаАртикулов.Колонки.Добавить("Артикул",

Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(50)));

ТаблицаАртикулов.Колонки.Добавить("Цена",

Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));

// заполнение строк

НоваяСтрока = ТаблицаАртикулов.Добавить();

НоваяСтрока.Артикул = "П-100245";

НоваяСтрока.Цена = 1250.50;

Проверьте, что в таблице нет строк с незаполненными ключевыми полями, если по ним планируется соединение: пустые значения дадут лишние строки с NULL или неожиданные совпадения.

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

Таблица передаётся через метод УстановитьПараметр, а в тексте запроса на неё ссылаются как на источник данных: ИЗ &ТаблицаАртикулов КАК ТаблицаАртикулов. Результат первого пакета помещают во временную таблицу.

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

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

"ВЫБРАТЬ

| ТаблицаАртикулов.Артикул КАК Артикул,

| ТаблицаАртикулов.Цена КАК Цена

|ПОМЕСТИТЬ ВТ_Артикулы

|ИЗ

| &ТаблицаАртикулов КАК ТаблицаАртикулов

|;

|

|ВЫБРАТЬ

| ВТ_Артикулы.Артикул КАК Артикул,

| ВТ_Артикулы.Цена КАК ЦенаИзФайла,

| Номенклатура.Ссылка КАК Номенклатура

|ИЗ

| ВТ_Артикулы КАК ВТ_Артикулы

| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура

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

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

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

Первый пакет запроса материализует таблицу значений во временную таблицу ВТ_Артикулы. Второй пакет соединяет её со справочником. Левое соединение сохранит строки из файла, даже если артикул в базе не найден — поле «Номенклатура» в таких строках будет NULL, что удобно для контроля незагруженных позиций.

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

Отбор по списку значений

Если нужна только фильтрация, соединение заменяют условием на вхождение: ГДЕ Документ.Номенклатура В (ВЫБРАТЬ Т.Ссылка ИЗ ВТ_Таблица КАК Т). Это эквивалент внутреннего соединения без умножения строк.

Соединение по нескольким полям

Ключ соединения может быть составным — например, организация плюс договор. Перечислите все условия через И в секции ПО. Следите за совпадением типов: соединение строки с числом не вызовет ошибку, но совпадений не найдёт.

Обращение к реквизитам ссылок из временной таблицы

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

Для больших таблиц добавьте во временную таблицу индекс: после ПОМЕСТИТЬ ВТ_Артикулы укажите ИНДЕКСИРОВАТЬ ПО Артикул. На объёмах от нескольких тысяч строк это заметно ускоряет соединение.
ПЗ
Практическое замечание

Ограничения и производительность

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

Если объём большой, рассмотрите альтернативы: загрузку данных в промежуточный регистр сведений, разбиение таблицы на порции с объединением результатов, либо перенос логики в СКД с набором данных-объектом.

Учитывайте, что временная таблица живёт в рамках одного выполнения запроса (или менеджера временных таблиц). Между отдельными вызовами Выполнить() без общего менеджера она не сохраняется.

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

Самая частая ошибка — «Поле не найдено» или «Неверные параметры в операции сравнения». Причины: несовпадение имён колонок с полями в запросе, не задан тип колонки, либо тип значения в строках не соответствует описанию.

Вторая группа ошибок — пустой результат при корректном запросе. Обычно это несовпадение данных: лишние пробелы в артикулах, разный регистр букв при сравнении в файловой базе, несоответствие типов в условии соединения.

Типичные ошибки
01
Колонки добавлены без ОписаниеТипов — при пустой или разнородной таблице запрос падает с ошибкой типа
02
Имя колонки в таблице не совпадает с именем поля в запросе — ошибка «Поле не найдено»
03
Соединение по строковому полю без обрезки пробелов — пустой результат соединения
04
Передача таблицы без параметра: забыли УстановитьПараметр — ошибка «Переменная не определена»
05
Использование временной таблицы во втором вызове Выполнить без менеджера временных таблиц — таблица не существует
Контрольные точки

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

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

Совпадает с ожиданием по логике соединения (при левом соединении — не меньше строк исходной таблицы)

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

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

Поля соединения
Норма

Ключевые поля заполнены, NULL только там, где соответствия реально нет

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

Все поля базы NULL — условие соединения не сработало

Время выполнения
Норма

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

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

Резкий рост времени при увеличении таблицы — нет индекса по полю соединения

Часто задаваемые вопросы

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

Нет, параметр-таблицу можно использовать только как источник в конструкции ИЗ &Таблица, а результат нужно куда-то поместить — во временную таблицу или сразу вывести как итоговый результат. На практике почти всегда делают ПОМЕСТИТЬ во временную таблицу и работают с ней дальше.

Чем передача таблицы отличается от условия В (&Массив)?

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

Работает ли этот механизм в СКД?

Да, но иначе. В СКД таблицу значений подключают как набор данных типа «Объект» с указанием имени параметра, а саму таблицу передают через свойство объекта настроек компоновщика. Внутри запроса СКД набор-объект описывается той же конструкцией ИЗ &Таблица.

Почему запрос с таблицей значений работает в толстом клиенте, но падает на сервере?

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

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

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

Итог

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

Таблица значений попадает в запрос через параметр и конструкцию ИЗ &Таблица ПОМЕСТИТЬ ВТ. Опишите колонки с типами, совместите имена колонок и полей запроса, при больших объёмах добавьте индекс и проверьте результат на дубли и NULL в полях соединения.