В чем разница между методами Выполнить и Выбрать при работе с запросами в 1С?

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

При изучении механизмов работы с данными в системе 1С:Предприятие 8 одним из самых важных и в то же время вызывающих вопросы моментов является работа с объектом Запрос. Часто начинающие разработчики путаются в том, что именно происходит в момент вызова методов Выполнить() и Выбрать(). Разберем детально каждый этап этой цепочки, проанализируем внутренние механизмы платформы и выясним, как правильно обрабатывать полученные данные.

Общая схема работы программного кода запроса

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


НашЗапрос = Новый Запрос; 
НашЗапрос.Текст = "
| ВЫБРАТЬ 
|   Ссылка, 
|   Наименование, 
|   Родитель КАК Группа 
| ИЗ 
|   Справочник.Номенклатура 
| ГДЕ 
|   Ссылка В ИЕРАРХИИ (&ВыбГруппа)"; 

НашЗапрос.УстановитьПараметр("ВыбГруппа", ВыбраннаяГруппаТоваров); 

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

Пока Выборка.Следующий() Цикл 
    Сообщить(Выборка.Наименование); 
КонецЦикла;

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

Шаг 1. Метод Выполнить() и объект РезультатЗапроса

Когда мы вызываем метод Выполнить(), платформа 1С отправляет сформированный текст запроса (вместе со значениями параметров) на SQL-сервер (в случае клиент-серверного варианта) или к движку файловой базы данных. В этот момент происходит физическое выполнение SQL-инструкции SELECT. СУБД находит нужные строки, фильтрует их согласно условию ГДЕ и подготавливает набор данных.

РезультатЗапроса — это объект, который выступает в роли ссылки на подготовленный набор данных на сервере. Важно понимать: после выполнения этой команды данные еще не «приехали» целиком в ваш программный код. Объект РезультатЗапроса позволяет нам:

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

Выясним причину, почему Выполнить() возвращает именно специальный объект, а не массив или таблицу. Это сделано для экономии ресурсов: если запрос вернул миллион строк, моментальная загрузка их в память (в объект ТаблицаЗначений) может привести к критической ошибке Out of Memory. РезультатЗапроса позволяет системе держать данные во временном хранилище сервера.

Шаг 2. Метод Выбрать() и концепция курсора

Рассмотрим подробнее команду Выбрать(). После того как РезультатЗапроса получен, нам нужно организовать перебор строк. Именно для этого создается объект ВыборкаИзРезультатаЗапроса.

С точки зрения системного программирования, Выборка — это динамический курсор. Метод Выбрать() инициализирует этот курсор и устанавливает указатель в позицию «перед первой строкой». Сами данные начинают подгружаться порциями (пакетами) по мере необходимости.

В чем преимущество использования выборки перед выгрузкой в таблицу значений? Разберем основные моменты:

  1. Экономия памяти: Платформа не копирует весь результат запроса целиком. Если вы прервете цикл на середине, лишние данные не будут переданы по сети.
  2. Работа с итогами: Если ваш запрос содержит ключевое слово ИТОГИ, то именно через метод Выбрать() вы сможете обходить данные иерархически (сначала общие суммы, затем детальные записи внутри них).
  3. Скорость: Создание объекта выборки происходит мгновенно, в отличие от метода Выгрузить(), который требует времени на создание структуры таблицы и заполнение каждой ячейки.

Шаг 3. Метод Следующий() и итерация

Проанализируем работу цикла Пока Выборка.Следующий() Цикл. Метод Следующий() выполняет две функции одновременно:

Только после успешного выполнения Следующий() мы получаем доступ к полям текущей записи (например, Выборка.Наименование).

Скрытые возможности и продвинутые методы

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

1. ОбходРезультатаЗапроса.Прямой — это поведение по умолчанию. Просто последовательное чтение строк сверху вниз.

2. ОбходРезультатаЗапроса.ПоГруппировкам — незаменим при работе с итогами. Рассмотрим пример кода для работы с иерархической выборкой:


// Предположим, в запросе есть ИТОГИ ПО Складу
Результат = Запрос.Выполнить();
ВыборкаСклад = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

Пока ВыборкаСклад.Следующий() Цикл
    // Здесь мы видим только итоги по складу
    Сообщить("Склад: " + ВыборкаСклад.Склад + " Итого: " + ВыборкаСклад.СуммаОстаток);
    
    // Вложенная выборка для детальных записей по товарам на ЭТОМ складе
    ВыборкаТовары = ВыборкаСклад.Выбрать();
    Пока ВыборкаТовары.Следующий() Цикл
        Сообщить("--- Товар: " + ВыборкаТовары.Номенклатура);
    КонецЦикла;
КонецЦикла;

3. Метод ВыполнитьПакет(). В современной разработке на платформе 8.3 часто используются пакетные запросы (несколько запросов в одном тексте, разделенных точкой с запятой). В этом случае обычный метод Выполнить() вернет результат только последнего запроса в пакете. Чтобы получить доступ к результатам всех запросов, необходимо использовать ВыполнитьПакет(), который возвращает Массив объектов РезультатЗапроса.

Краткие выводы для закрепления

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

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

← На главную