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