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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки на платформе 1С:Предприятие часто возникает ситуация, когда данные уже находятся в оперативной памяти (например, в таблице части формы или в коллекции ДанныеФормыКоллекция), но для дальнейшей обработки их нужно объединить с данными базы данных или быстро получить дополнительные реквизиты ссылок. Самым эффективным инструментом для этого является механизм запросов.

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

Метод 1: Использование временных таблиц в запросе

Это классический и наиболее универсальный способ. Если у нас есть объект ТаблицаЗначений (полученный, например, методом Выгрузить() из данных формы "Корзина"), мы можем поместить его во временную таблицу внутри запроса. Рассмотрим этот процесс по шагам.

Главная деталь, о которой часто забывают начинающие разработчики — необходимость использования объекта МенеджерВременныхТаблиц. Без него запрос не сможет "удержать" данные переданной таблицы во временном хранилище СУБД для последующего обращения к ним.

Проанализируем правильную структуру кода:


// 1. Подготовка исходной таблицы значений (на сервере)
ТЗ = Корзина.Выгрузить(); 

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

// 3. Текст запроса с помещением ТЗ во временную таблицу
Запрос.Текст = 
    "ВЫБРАТЬ
    |    ВременнаяТаблица.ЗаказПоставщику КАК ЗаказПоставщику
    |ПОМЕСТИТЬ ВТЗаказы
    |ИЗ
    |    &ВременнаяТаблица КАК ВременнаяТаблица
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |    ВТЗаказы.ЗаказПоставщику.Номер КАК Номер,
    |    ВТЗаказы.ЗаказПоставщику.Контрагент КАК Контрагент,
    |    ВТЗаказы.ЗаказПоставщику.Дата КАК Дата
    |ИЗ
    |    ВТЗаказы КАК ВТЗаказы";

// 4. Передача ТЗ в качестве параметра
Запрос.УстановитьПараметр("ВременнаяТаблица", ТЗ);

// 5. Выполнение и получение результата
Выборка = Запрос.Выполнить().Выгрузить();

Важное замечание: Обращение к реквизитам через точку (например, ВТЗаказы.ЗаказПоставщику.Номер) в запросе порождает неявное левое соединение (LEFT JOIN) с таблицей документа. Если строк в таблице много, это может сказаться на производительности. Для оптимизации лучше выполнять явное соединение с основной таблицей документа по ссылке.

Метод 2: Оптимизация через типизацию и индексирование

При работе с большими объемами данных или составными типами данных в колонках ТЗ, запрос может работать некорректно или медленно. Разберем, как улучшить наш подход.

Во-первых, платформа должна точно знать типы данных в колонках ТаблицаЗначений. Если таблица создается программно, всегда указывайте ОписаниеТипов. Если же данные выгружаются из формы, рекомендуется использовать оператор ВЫРАЗИТЬ в тексте запроса. Это помогает SQL-оптимизатору заранее определить, к каким физическим таблицам обращаться.

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

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


Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    ВЫРАЗИТЬ(ВременнаяТаблица.ЗаказПоставщику КАК Документ.ЗаказПоставщику) КАК ЗаказСсылка
    |ПОМЕСТИТЬ ВТЗаказы
    |ИЗ
    |    &ВременнаяТаблица КАК ВременнаяТаблица
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |    Заказы.Номер,
    |    Заказы.Дата,
    |    Заказы.Контрагент
    |ИЗ
    |    ВТЗаказы КАК ВТЗаказы
    |    ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ЗаказПоставщику КАК Заказы
    |    ПО ВТЗаказы.ЗаказСсылка = Заказы.Ссылка
    |ИНДЕКСИРОВАТЬ ПО
    |    ЗаказСсылка";

Запрос.УстановитьПараметр("ВременнаяТаблица", ТЗ);
Результат = Запрос.Выполнить();

Метод 3: Передача массива ссылок (упрощенный вариант)

Если нам не нужно передавать дополнительные данные из строк таблицы (например, количество или цену, которые изменил пользователь в форме), а нужно просто получить реквизиты объектов по списку ссылок, можно использовать более простой метод — передачу массива в условие ГДЕ ... В (&Массив).

Этот способ избавляет от необходимости создавать МенеджерВременныхТаблиц и описывать структуру временной таблицы. Выясним, как это выглядит на практике:


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

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    Заказ.Номер,
    |    Заказ.Дата,
    |    Заказ.Контрагент
    |ИЗ
    |    Документ.ЗаказПоставщику КАК Заказ
    |ГДЕ
    |    Заказ.Ссылка В (&МассивЗаказов)";

Запрос.УстановитьПараметр("МассивЗаказов", МассивЗаказов);
Выборка = Запрос.Выполнить().Выбрать();

Ограничение: Стоит учитывать, что при передаче очень больших массивов (свыше 10-20 тысяч элементов) СУБД может столкнуться с ограничениями на длину запроса. В таких случаях метод с временной таблицей (Метод 1) является более надежным.

Метод 4: Использование Библиотеки Стандартных Подсистем (БСП)

Если ваша конфигурация разработана на базе современных типовых решений (например, УТ 11, ERP, БП 3.0), в ней наверняка присутствует БСП. Она предлагает готовые функции, которые позволяют получить значения реквизитов объектов без написания текста запроса вручную.

Функция ОбщегоНазначения.ЗначенияРеквизитовОбъектов принимает массив ссылок и строку с именами нужных полей. Это сокращает код до одной-двух строк:


// Получаем массив ссылок из таблицы
СписокСсылок = Корзина.ВыгрузитьКолонку("ЗаказПоставщику");

// Получаем соответствие (или таблицу) с данными
ДанныеЗаказов = ОбщегоНазначения.ЗначенияРеквизитовОбъектов(СписокСсылок, "Номер, Контрагент, Дата");

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

Типичные ошибки и нюансы

  1. Ошибка "Поле не найдено": Чаще всего возникает, когда в первом запросе пакета (где происходит ПОМЕСТИТЬ) вы не переименовали колонку или во втором запросе обращаетесь к имени, которого нет в ТЗ. Всегда проверяйте соответствие имен в конструкции ВЫБРАТЬ ... КАК ИмяПоля.
  2. Передача данных с клиента: Помните, что объект Запрос и ТаблицаЗначений доступны только на сервере. Если вы находитесь в контексте клиентской процедуры формы, данные коллекции ДанныеФормыКоллекция нужно передать на сервер, там выполнить Выгрузить() и только потом запускать запрос.
  3. Пустые ссылки: При выполнении запроса к ТЗ, содержащей пустые ссылки, обращение через точку может вернуть NULL или привести к непредвиденным результатам в соединениях. Используйте ВНУТРЕННЕЕ СОЕДИНЕНИЕ, если пустые значения вам не нужны в результате.

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

← На главную