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