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