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

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

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

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

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

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

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

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

Платформа 1С умеет преобразовать таблицу значений, переданную как параметр запроса, во временный набор данных, доступный внутри текста запроса. В тексте запроса такой параметр записывается с амперсандом — &ТЗ — и используется в предложении ИЗ как обычный источник данных с обязательным псевдонимом.

Колонки таблицы значений становятся полями этого источника. Обращение к ним выполняется через псевдоним: ТЗ.Номенклатура, ТЗ.Количество. Состав и типы полей полностью определяются тем, какие колонки были добавлены в таблицу значений в коде, и какие типы им назначены.

Важно понимать ограничение: параметр с таблицей значений можно использовать только как источник в предложении ИЗ. Нельзя передать таблицу в условие ГДЕ напрямую или сравнивать её с чем-либо — сначала нужно выбрать из неё данные, обычно с помещением во временную таблицу.

Шаг 1. Подготовьте таблицу значений с типизированными колонками

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

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

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

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

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

НоваяСтрока = ТЗ.Добавить();

НоваяСтрока.Номенклатура = СсылкаНаТовар;

НоваяСтрока.Количество = 5;

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

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

Шаг 2. Передайте таблицу в запрос и обратитесь к ней в тексте

Передача выполняется методом УстановитьПараметр. Имя параметра в коде и в тексте запроса должно совпадать. Минимальный рабочий пример:

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

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

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

"ВЫБРАТЬ

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

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

|ИЗ

| &ТЗ КАК ТЗ";

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

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

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

Шаг 3. Поместите таблицу во временную таблицу и соедините с данными базы

На практике таблицу значений почти всегда сразу помещают во временную таблицу — это позволяет использовать её в нескольких запросах пакета и индексировать для ускорения соединений. Для временных таблиц нужен менеджер временных таблиц.

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

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

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

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

"ВЫБРАТЬ

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

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

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

|ИЗ

| &ТЗ КАК ТЗ

|

|ИНДЕКСИРОВАТЬ ПО

| Номенклатура

|;

|

|ВЫБРАТЬ

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

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

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

|ИЗ

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

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

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

Конструкция ИНДЕКСИРОВАТЬ ПО ускоряет соединение, когда в таблице много строк. Левое соединение с ЕСТЬNULL защищает от NULL в случае, когда для части позиций остатков нет.

Соединение по строковым полям

Если соединение идёт по строковому полю (например, по артикулу или коду), убедитесь, что длина строки в описании типов колонки не меньше длины соответствующего реквизита в базе. Иначе значения могут обрезаться, и соединение не сработает без какого-либо сообщения об ошибке — это одна из самых коварных причин «пустого» результата.

Фильтрация данных базы по таблице значений

Обратная задача — отобрать из базы только то, что есть в таблице значений. Для этого временную таблицу используют в условии через внутреннее соединение или через В (ВЫБРАТЬ ...). Внутреннее соединение обычно читается проще и работает предсказуемее.

Альтернатива: условие В (&Список) без таблицы значений

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

МассивТоваров = ТЗ.ВыгрузитьКолонку("Номенклатура");

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

// В тексте запроса: ГДЕ Товары.Ссылка В (&СписокТоваров)

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

Параметр с таблицей значений (&ТЗ)

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

Массив в условии В (&Список)

Проще и быстрее, когда нужна одна колонка для фильтра. Не позволяет соединять по нескольким полям.

Временная таблица из другого запроса

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

Типичные ошибки и ограничения

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

Типичные ошибки
01
Колонка добавлена без ОписаниеТипов — запрос падает с ошибкой типа или соединение не работает
02
Строковая колонка без ограничения длины — ошибка при сравнении или соединении по этому полю
03
Параметр в тексте указан без амперсанда или с другим именем — ошибка «Параметр не найден»
04
Попытка использовать &ТЗ в условии ГДЕ — синтаксическая ошибка, таблицу можно использовать только в ИЗ
05
Забыт МенеджерВременныхТаблиц при использовании ПОМЕСТИТЬ — временная таблица не создаётся
06
Пустая таблица значений без строк: запрос выполнится, но вернёт пустой результат — проверяйте заполненность до выполнения

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

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

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

Запрос выполняется без исключений
Норма

Выполнить() отрабатывает, ошибок типов нет

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

Ошибка о несовместимости типов или «поле не найдено»

Состав полей результата
Норма

Все колонки таблицы значений присутствуют и заполнены

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

Поля есть, но значения NULL — соединение не сработало

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

Число строк соответствует ожиданию с учётом соединений

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

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

Как проверить, что обращение к таблице сработало

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

Также полезно проверить исходную таблицу значений до запроса: ТЗ.Количество() и тип значения в ключевой колонке через ТипЗнч(ТЗ[0].Номенклатура). Это занимает секунды и отсекает половину возможных причин пустого результата ещё до запуска запроса.

Держите имена колонок таблицы значений совпадающими с именами полей базы, с которыми они соединяются (Номенклатура, Склад, Контрагент). Это заметно упрощает чтение запроса и снижает число ошибок при доработках.
ПЗ
Практическое замечание

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

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

Да. Параметр &ТЗ можно напрямую соединять с таблицами базы в одном запросе. Но помещение во временную таблицу удобнее: её можно индексировать и использовать в нескольких запросах пакета.

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

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

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

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

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

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

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

В СКД таблица значений подключается как внешний набор данных: в схеме компоновки добавляется источник данных типа «Объект», а при программном формировании отчёта таблица передаётся через коллекцию внешних наборов в ПроцессорКомпоновкиДанных. Параметр &ТЗ в СКД не используется.

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

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

Итог

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

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