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

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

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

Как получить значение из выборки результата запроса в 1С: обход через Следующий, поиск через Найти, доступ к полям, типичные ошибки и примеры кода на встроенном языке.

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

На практике задача сводится к трём сценариям: перебрать все строки выборки циклом, найти одну нужную строку методом НайтиСледующий или Найти у таблицы, либо получить единственное значение скалярного запроса. У каждого сценария свой код и свои подводные камни — например, обращение к несуществующему полю вызывает ошибку, а попытка прочитать NULL без проверки ломает дальнейшие вычисления.

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

Создание выборки из результата запроса

Выборка появляется только после выполнения запроса. Минимальная последовательность выглядит так: создать объект Запрос, задать текст, установить параметры, выполнить и вызвать у результата метод Выбрать().

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

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

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Товар,

| Номенклатура.Код КАК Код

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| Номенклатура.Родитель = &Группа";

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

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

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

Метод Выбрать() принимает два необязательных параметра: тип обхода (ОбходРезультатаЗапроса.Прямой, ПоГруппировкам или ПоГруппировкамСИерархией) и имя группировки. Для плоского списка строк достаточно вызова без параметров — это самый частый вариант.

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

Обход выборки циклом и чтение значений полей

Стандартный приём — цикл Пока Выборка.Следующий() Цикл. Метод Следующий() переводит курсор на следующую строку и возвращает Истина, если строка есть. Внутри цикла поля доступны через точку по имени из секции ВЫБРАТЬ.

Пока Выборка.Следующий() Цикл

ТоварСсылка = Выборка.Товар;

КодТовара = Выборка.Код;

// дальнейшая обработка значений

КонецЦикла;

Имя поля — это псевдоним, заданный через КАК в тексте запроса. Если псевдоним не указан, платформа формирует его автоматически, но опираться на это не стоит: всегда давайте полям явные имена. Доступ по индексу возможен через Выборка[0], однако такой код хрупок — при изменении порядка полей в запросе он начнёт возвращать не те данные.

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

Порядок действий
  1. 1
    Сформируйте текст запроса и задайте псевдонимы полей через КАК
  2. 2
    Установите параметры запроса методом УстановитьПараметр
  3. 3
    Выполните запрос и проверьте результат методом Пустой()
  4. 4
    Создайте выборку методом Выбрать()
  5. 5
    Позиционируйтесь на строку: Следующий() или НайтиСледующий()
  6. 6
    Прочитайте значение: Выборка.ИмяПоля, при необходимости проверив его на NULL

Поиск конкретной строки в выборке

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

Отбор = Новый Структура("Товар", ИскомаяСсылка);

Если Выборка.НайтиСледующий(Отбор) Тогда

НайденныйКод = Выборка.Код;

Иначе

// строка не найдена

КонецЕсли;

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

Если поиск выполняется многократно и в произвольном порядке, правильнее выгрузить результат в таблицу значений (РезультатЗапроса.Выгрузить()) и пользоваться методом Найти() таблицы — он ищет с начала. Для частых обращений таблицу дополнительно индексируют методом Индексы.Добавить("Товар").

Сравнение способов доступа

Выборка + Следующий()

Подходит для однократного последовательного перебора. Минимальный расход памяти, но нельзя вернуться назад.

Выборка + НайтиСледующий()

Поиск строки вперёд от текущей позиции. Удобен при совпадающем порядке обращений, не подходит для повторного поиска.

Выгрузить() в таблицу значений

Произвольный доступ через Найти() и НайтиСтроки(), возможна индексация. Требует больше памяти при больших объёмах.

СКД или запрос с отбором

Если строка известна заранее, эффективнее отфильтровать её прямо в запросе через ГДЕ, а не искать в выборке.

Получение единственного значения и работа с NULL

Скалярный запрос — например, сумма остатков или количество документов — возвращает одну строку. Код получения значения выглядит так:

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда

Остаток = Выборка.КоличествоОстаток;

Иначе

Остаток = 0;

КонецЕсли;

Главная ловушка — значение NULL. Оно появляется при левом соединении без совпадений или при агрегатных функциях над пустым набором (кроме КОЛИЧЕСТВО). Арифметика с NULL вызывает ошибку, поэтому значение нужно либо обрабатывать в запросе функцией ЕСТЬNULL(Поле, 0), либо проверять в коде:

Если Выборка.КоличествоОстаток = NULL Тогда

Остаток = 0;

Иначе

Остаток = Выборка.КоличествоОстаток;

КонецЕсли;

Предпочтительнее обработка на уровне запроса через ЕСТЬNULL: код становится проще, а проверка выполняется один раз при выборке данных, а не в каждой строке обхода.

Итоги, группировки и иерархический обход

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

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

Пока ВыборкаГруппы.Следующий() Цикл

ГруппаТовара = ВыборкаГруппы.Товар; // значение группировки

ВыборкаДетали = ВыборкаГруппы.Выбрать();

Пока ВыборкаДетали.Следующий() Цикл

// детальные записи внутри группы

КонецЦикла;

КонецЦикла;

У выборки по группировкам доступно поле ТипЗаписи(), которое позволяет отличить итоговую строку от детальной. Это важно при обходе с иерархией: без проверки типа записи легко обработать итог как обычную строку и задвоить данные.

Значения итоговых полей (сумм, количеств) читаются в строке группировки точно так же — через точку по имени агрегатного поля из запроса.

Типичные ошибки
01
Обращение к полю, которого нет в тексте запроса, — возникает исключение «Поле не найдено». Сверяйте псевдонимы в секции ВЫБРАТЬ.
02
Чтение поля до вызова Следующий() — курсор ещё не позиционирован, значения не определены.
03
Отсутствие обработки NULL — арифметика или сравнение с NULL приводит к ошибке или неверному результату.
04
Повторный обход той же выборки — после первого прохода курсор в конце, цикл просто не выполнится.
05
Использование НайтиСледующий() для повторного поиска уже пройденной строки — метод ищет только вперёд.
06
Запрос в цикле вместо соединения таблиц — кратно увеличивает нагрузку на сервер СУБД.

Проверка результата и отладка выборки

Быстрый способ убедиться, что запрос возвращает ожидаемые данные, — выгрузить результат в таблицу значений и посмотреть её в отладчике: ТЗ = РезультатЗапроса.Выгрузить() и точка останова на следующей строке. В таблице видны все поля, их типы и значения, включая NULL.

Для проверки в пользовательском режиме удобна консоль запросов: она показывает результат до написания кода, что позволяет заранее убедиться в правильности соединений, отборов и псевдонимов полей.

Признаки корректно работающего кода: РезультатЗапроса.Пустой возвращает Ложь при наличии данных, первый вызов Следующий() даёт Истина, значения полей имеют ожидаемый тип и не равны NULL без необходимости.

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

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

РезультатЗапроса.Пустой()
Норма

Возвращает Ложь при наличии строк

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

Истина при ожидаемых данных — проверяйте параметры и условие ГДЕ

Выборка.Следующий()
Норма

Первый вызов возвращает Истина

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

Сразу Ложь — выборка пуста или уже пройдена

Значение поля
Норма

Ожидаемый тип: ссылка, число, строка, дата

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

NULL там, где должно быть значение, — добавьте ЕСТЬNULL в запрос

Выгрузка в таблицу значений
Норма

Все поля из запроса присутствуют с заданными псевдонимами

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

Нет нужной колонки — поле не добавлено в секцию ВЫБРАТЬ

Частые вопросы

Как получить значение поля, если заранее неизвестно его имя?

Выгрузите результат в таблицу значений и обратитесь к колонке по имени динамически: СтрокаТЗ[ИмяКолонки]. У самой выборки динамический доступ тоже возможен через квадратные скобки: Выборка[ИмяПоля].

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

Либо запрос вернул пустой результат (проверьте параметры и условия отбора), либо выборка уже была пройдена ранее — курсор стоит в конце. Создайте выборку заново методом Выбрать() у результата запроса.

Чем отличается Выбрать() от Выгрузить()?

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

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

Используйте квадратные скобки с номером колонки: Выборка[0] — первое поле результата. Учтите, что такой код зависит от порядка полей в запросе, поэтому обращение по имени надёжнее.

Что делать, если НайтиСледующий() не находит строку, которая точно есть?

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

Как безопасно получить числовое значение, которое может быть NULL?

Лучшее решение — обернуть поле в запросе функцией ЕСТЬNULL(Поле, 0). Альтернатива — проверка в коде: если значение равно NULL, присвоить переменной значение по умолчанию до любых вычислений.

Итог

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

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