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

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

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

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

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

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

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

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

Когда вы устанавливаете параметр запроса значением типа «ТаблицаЗначений», платформа сериализует её и передаёт на сервер СУБД как набор строк. В тексте запроса такой параметр можно использовать в конструкции ВЫБРАТЬ ... ИЗ &ИмяПараметра — поля таблицы становятся доступны по именам колонок.

Ключевое ограничение: колонки таблицы значений должны иметь явно заданные типы. Если колонка создана без типизации (например, просто ТЗ.Колонки.Добавить("Номенклатура") без второго параметра), платформа не сможет сформировать корректную структуру на стороне СУБД, и запрос завершится ошибкой. Поэтому типизация через ОписаниеТипов — обязательный шаг подготовки.

Способ 1: параметр запроса и конструкция ПОМЕСТИТЬ

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

Пример полного кода:

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

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

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

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

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

СтрокаТЗ.Номенклатура = Справочники.Номенклатура.НайтиПоКоду("000000001");

СтрокаТЗ.Количество = 10;

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

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

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

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

"ВЫБРАТЬ

| ТаблицаТоваров.Номенклатура КАК Номенклатура,

| ТаблицаТоваров.Количество КАК Количество

|ПОМЕСТИТЬ ВТ_Товары

|ИЗ

| &ТаблицаТоваров КАК ТаблицаТоваров

|;

|

|ВЫБРАТЬ

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

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

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

|ИЗ

| ВТ_Товары КАК ВТ

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

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

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

Обратите внимание на два момента. Во-первых, менеджер временных таблиц нужно создать явно, иначе временная таблица ВТ_Товары не сохранится между пакетами. Во-вторых, псевдонимы полей лучше задавать сразу — это упрощает чтение последующих запросов.

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

Способ 2: МенеджерВременныхТаблиц и ПоместитьТаблицуЗначений

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

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

МенеджерВТ.ПоместитьТаблицуЗначений(ТЗ, "ВТ_Товары");

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

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

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

"ВЫБРАТЬ

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

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

|ИЗ

| ВТ_Товары КАК ВТ";

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

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

Требование к типизации здесь ещё строже: метод ПоместитьТаблицуЗначений формирует структуру временной таблицы по типам колонок, и нетипизированная колонка приведёт к ошибке на этапе вызова метода, а не запроса.

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

Параметр запроса + ПОМЕСТИТЬ

Универсально, весь код в одном месте. Подходит, когда таблица нужна в одном запросе. Минус — лишний пакет в тексте запроса.

МенеджерВТ.ПоместитьТаблицуЗначений

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

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

Если данные можно получить запросом к базе, лучше не выгружать их в ТЗ вообще — соединяйтесь напрямую, это быстрее.

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

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

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

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

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

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

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

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

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

Количество строк во временной таблице
Норма

Совпадает с числом строк исходной ТЗ

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

Меньше или ноль — проверяйте типизацию колонок и заполнение ТЗ

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

Совпадающие ссылки дают заполненные поля

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

Все поля соединения NULL — разные типы ссылок или пустые значения в ТЗ

Типы полей результата
Норма

Поля имеют ожидаемые типы (ссылка, число)

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

Поле имеет составной тип или строку неограниченной длины

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

Самая частая ошибка — «Неверные параметры в операции сравнения» или падение запроса из-за нетипизированной колонки. Лечится явным указанием ОписаниеТипов при создании колонки. Вторая по частоте — обращение к временной таблице в другом запросе без общего менеджера временных таблиц: каждый объект Запрос без явно назначенного менеджера создаёт свой собственный, и временные таблицы между ними не видны.

Ещё одна проблема — имена колонок, совпадающие с зарезервированными словами языка запросов (например, «Период», «Номер» обычно допустимы, но лучше давать осмысленные уникальные имена). Также не забывайте, что таблица значений с колонкой типа «ХранилищеЗначения» или «Картинка» не может быть передана в запрос осмысленно — такие колонки следует исключить.

Типичные ошибки
01
Колонка без типа — запрос падает с ошибкой на этапе выполнения; всегда задавайте ОписаниеТипов
02
Строка неограниченной длины в соединении — ошибка запроса; ограничьте длину через КвалификаторыСтроки
03
Разные менеджеры временных таблиц у запросов — временная таблица «не видна»; передавайте один МенеджерВТ всем запросам
04
Составной тип ссылки — медленные соединения и неожиданные результаты; указывайте конкретный тип ссылки
05
Передача огромной ТЗ вместо запроса к базе — лишняя нагрузка на память и СУБД

Когда таблицу значений лучше не использовать

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

Для фильтрации по списку значений также не обязательно строить таблицу: достаточно передать массив или список значений параметром и использовать условие ГДЕ Номенклатура В (&СписокНоменклатуры). Таблица значений нужна именно тогда, когда передаётся несколько связанных колонок — например, пары «номенклатура + количество + цена».

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

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

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

Почему запрос с параметром-таблицей работает медленно?

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

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

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

Что делать, если колонка содержит значения разных типов?

Приведите значения к одному типу до передачи в запрос. Если это невозможно, задайте составной тип в ОписаниеТипов, но учтите, что соединения по таким полям будут медленнее и могут требовать явного приведения через ВЫРАЗИТЬ(... КАК ...) в тексте запроса.

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

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

Итог

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

Таблица значений передаётся в запрос параметром и помещается во временную таблицу через ПОМЕСТИТЬ либо методом МенеджерВТ.ПоместитьТаблицуЗначений. Обязательна типизация колонок через ОписаниеТипов и общий менеджер временных таблиц для всех связанных запросов. Если данные уже есть в базе — используйте прямой запрос без промежуточной таблицы значений.