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