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