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