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

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

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

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

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

Механизм прост: таблица значений передаётся в запрос через параметр, в тексте запроса она выбирается конструкцией ВЫБРАТЬ ... ИЗ &Таблица КАК ТЗ, после чего её можно поместить во временную таблицу и использовать дальше — в соединениях, группировках, условиях. Это стандартный приём, поддерживаемый платформой без дополнительных расширений.

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

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

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

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

ТЗ = Новый ТаблицаЗначений;

ТЗ.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));

ТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));

ТЗ.Колонки.Добавить("Комментарий", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(100)));

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

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

Базовый сценарий: создать объект Запрос, установить параметр с таблицей и описать выборку из неё. Имя параметра в тексте запроса должно совпадать с именем в методе УстановитьПараметр.

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

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

"ВЫБРАТЬ

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

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

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

|ИЗ

| &ТЗ КАК ТЗ";

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

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

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

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

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

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

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

ВЫБРАТЬ

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

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

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

ИЗ

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

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

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

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

Соединение по строковым полям (например, по артикулу или наименованию) работает медленнее и чувствительно к пробелам и регистру. Надёжнее заранее сопоставить строковые ключи со ссылками отдельным запросом и соединяться уже по ссылкам.

bsl
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.УстановитьПараметр("ТЗ", ТЗ);
Запрос.Выполнить();

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

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

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

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

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

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

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

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

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

Параметр запроса (&ТЗ)

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

Внешний набор данных в СКД

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

Перебор строк в коде

Просто для маленьких таблиц и одиночных операций. Медленно и громоздко при соединениях с данными базы — для каждой строки идёт отдельное обращение.

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

Подходит для очень больших объёмов и многоразового использования. Требует изменения конфигурации и записи данных в базу.

Типичные ошибки и их признаки

Самая частая ошибка — «Неверные параметры в операции сравнения» или несовпадение типов при соединении: колонка таблицы имеет составной тип, а поле регистра — конкретный. Лечится явным описанием типа колонки или приведением через ВЫРАЗИТЬ(... КАК ...) в запросе.

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

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

Типичные ошибки
01
Колонки без описания типов — запрос падает или соединение не работает из-за составного типа
02
Соединение по строковым полям без нормализации — пропуски строк из-за пробелов и регистра букв
03
Внутреннее соединение вместо левого — теряются строки таблицы, которым нет пары в базе
04
Установка параметра после Выполнить() — ошибка или пустой результат
05
Отсутствие Закрыть() у менеджера временных таблиц — рост потребления памяти в длительных обработках
Контрольные точки

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

Состав колонок
Норма

Каждая колонка имеет конкретный тип, ссылочные поля — конкретный тип ссылки

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

Составной или пустой тип, смешанные значения в одной колонке

Временная таблица
Норма

Запрос ВЫБРАТЬ * ИЗ ВТ_Данные возвращает все строки исходной таблицы

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

Пустой результат при заполненной таблице — проверять параметр

Соединение с базой
Норма

Число строк результата соответствует ожиданию, нет неожиданных дублей

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

Строк разом стало больше — детализация правой таблицы не свёрнута

FAQ

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

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

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

Таблица значений реквизита формы передаётся в запрос так же, через УстановитьПараметр, но код должен выполняться на сервере — оформите вызов серверной процедурой и передайте таблицу как параметр или через ДанныеФормыВЗначение.

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

Нет, запрос только читает переданную таблицу. Чтобы получить изменённые данные, выгрузите результат запроса в новую таблицу методом Результат.Выгрузить() и работайте уже с ней.

Что делать, если таблица содержит сотни тысяч строк?

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

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

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

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

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

Итог

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

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