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

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

Как получить данные из запроса в 1С: выборка, таблица значений и практические примеры

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

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

Типовая схема работы выглядит так: создаётся объект Запрос, задаётся текст на встроенном языке запросов, при необходимости устанавливаются параметры, после чего вызывается Выполнить(). Результат — объект РезультатЗапроса, из которого данные извлекаются методами Выбрать() или Выгрузить(). Ошибки чаще всего возникают не в тексте запроса, а именно на этапе обхода результата: пустая выборка, неверное имя поля, обращение к сгруппированным итогам.

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

Базовая схема: создание, параметры и выполнение запроса

Минимальный рабочий фрагмент получения данных выглядит так:

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

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

"ВЫБРАТЬ

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

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

|ИЗ

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

|ГДЕ

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

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

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

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

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

Сообщить(Выборка.Наименование);

КонецЦикла;

Ключевые моменты этого кода. Параметры в тексте обозначаются символом & и обязательно заполняются через УстановитьПараметр() до выполнения — иначе запрос упадёт с ошибкой «Параметр не найден». Метод Выполнить() возвращает РезультатЗапроса, а уже из него создаётся выборка методом Выбрать(). Обход выполняется циклом Пока Выборка.Следующий() Цикл: каждый вызов Следующий() переводит указатель на следующую строку и возвращает Истина, пока строки не закончатся.

Обращение к полям выборки идёт по псевдонимам, заданным в тексте запроса после ключевого слова КАК. Если псевдоним не задан, платформа сформирует имя автоматически, но полагаться на это не стоит — явные псевдонимы делают код устойчивым к изменениям запроса.

Обход выборки: построчная обработка данных

Метод Выбрать() возвращает объект ВыборкаИзРезультатаЗапроса — последовательный курсор по строкам результата. Это основной способ, когда данные нужно обработать по одной записи: создать документы, заполнить табличную часть, выполнить проверки по каждой строке.

Линейный обход и обход по группировкам

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

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

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

Сообщить("Группа: " + ВыборкаГруппы.Склад);

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

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

Сообщить(" " + ВыборкаДетали.Номенклатура);

КонецЦикла;

КонецЦикла;

Дополнительные полезные методы выборки: Количество() — число строк без обхода, СледующийПоЗначениюПоля("Склад") — переход к следующему значению конкретного поля, что удобно при обработке упорядоченных данных без явных итогов.

Когда выборка предпочтительнее таблицы значений

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

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

Метод Выгрузить() материализует весь результат запроса в памяти. Без параметров он возвращает ТаблицаЗначений:

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

Для Каждого Строка Из ТаблицаРезультат Цикл

Сообщить(Строка.Наименование);

КонецЦикла;

// Поиск и индексный доступ

НайденныеСтроки = ТаблицаРезультат.НайтиСтроки(Новый Структура("Склад", СкладМагазина));

ПерваяСтрока = ТаблицаРезультат[0];

Таблица значений удобна, когда данные нужно перебирать многократно, искать по ним (Найти(), НайтиСтроки()), сортировать (Сортировать()), сворачивать (Свернуть()) или передавать между процедурами и в табличные поля формы. Именно таблица значений — стандартный способ заполнить табличную часть документа из запроса: Объект.Товары.Загрузить(ТаблицаРезультат).

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

Выбор способа получения данных

Выборка (Выбрать)

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

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

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

Дерево значений (Выгрузить с ПоГруппировкам)

Иерархические данные с итогами, вывод в дерево на форме. Требует ИТОГИ ПО в запросе.

Прямая запись в СКД/отчёт

Когда результат нужен только для отчёта — данные отдаются компоновке без ручного обхода.

Проверка результата: пустой запрос и права доступа

Частая ситуация: запрос выполнился без ошибок, но строк нет. Перед обработкой стоит проверять результат методом Пустой():

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

Если РезультатЗапроса.Пустой() Тогда

Возврат; // нечего обрабатывать

КонецЕсли;

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

Пустой результат — не всегда ошибка логики. Типовые причины: параметр отбора не заполнен или содержит пустую ссылку, отбор по дате не попадает в период данных, у текущего пользователя ограничены права на чтение объектов (тогда запрос «молча» вернёт меньше строк, чем ожидается), а также соединение таблиц, которое отсекает все записи из-за несовпадения ключей.

Признак проблемы с параметрами: в консоли запросов тот же текст с теми же параметрами возвращает строки, а в коде — нет. В этом случае проверяйте тип передаваемого значения: например, строка вместо ссылки или дата без времени при сравнении с датой документа.

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

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

Количество строк
Норма

Выборка.Количество() больше нуля, данные соответствуют отбору

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

Пустой() = Истина при заведомо существующих данных — проверять параметры и права

Имена полей
Норма

Обращение Выборка.Поле работает без ошибок

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

Ошибка «Поле не обнаружено» — псевдоним в запросе не совпадает с кодом

Типы значений
Норма

Поля ссылочных типов содержат ссылки, даты — даты

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

Неопределено или NULL в полях — левое соединение не нашло пару, нужна проверка ЕСТЬNULL

Работа с NULL и соединениями таблиц

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

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

"ВЫБРАТЬ

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

| ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток

|ИЗ

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

| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки

| ПО Товары.Ссылка = Остатки.Номенклатура";

Если ЕСТЬNULL не использовано, в коде значение проверяют через Выборка.Остаток = NULL или ЗначениеЗаполнено() с осторожностью: ЗначениеЗаполнено(NULL) вернёт Ложь, что иногда используют как признак отсутствия связанной записи, но явная проверка на NULL читается надёжнее.

Временные таблицы и пакетные запросы

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

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

Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;

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

"ВЫБРАТЬ

| Реализация.Ссылка КАК Документ

|ПОМЕСТИТЬ ВТ_Документы

|ИЗ

| Документ.РеализацияТоваровУслуг КАК Реализация

|ГДЕ

| Реализация.Дата МЕЖДУ &Начало И &Конец

|;

|ВЫБРАТЬ

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

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

| Товары.Количество КАК Количество

|ИЗ

| ВТ_Документы КАК ВТ

| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг.Товары КАК Товары

| ПО ВТ.Документ = Товары.Ссылка";

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

Таблица = Результат.Выгрузить();

Метод Выполнить() в пакетном запросе возвращает результат последнего запроса пакета. Если нужны результаты нескольких запросов пакета, используется ВыполнитьПакет() — он возвращает массив результатов в порядке следования запросов в тексте. Временные таблицы живут в рамках менеджера временных таблиц: пока объект существует, к ВТ_Документы можно обращаться из последующих запросов, что удобно для поэтапной выборки без повторных соединений.

Порядок получения данных из запроса
  1. 1
    Создайте объект Запрос и задайте текст с явными псевдонимами полей
  2. 2
    Установите все параметры через УстановитьПараметр до выполнения
  3. 3
    Выполните запрос и проверьте результат методом Пустой()
  4. 4
    Выберите способ извлечения: Выбрать() для построчного обхода или Выгрузить() для таблицы значений
  5. 5
    Обработайте NULL через ЕСТЬNULL в тексте запроса
  6. 6
    Проверьте результат на копии базы перед запуском на рабочих данных

Типичные ошибки при получении данных из запроса

Большинство проблем при работе с результатом запроса сводится к нескольким повторяющимся сценариям. Их знание экономит время отладки заметно сильнее, чем знание редких методов объекта запроса.

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

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

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

FAQ

Чем отличается Выполнить() от ВыполнитьПакет()?

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

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

У выборки есть метод Количество(): Выборка.Количество(). У таблицы значений — Количество() или свойство через Таблица.Количество(). Альтернатива на уровне запроса — функция КОЛИЧЕСТВО(*) в отдельном запросе, если нужно только число.

Почему запрос в коде возвращает пусто, а в консоли запросов — строки?

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

Как получить только первую строку результата?

Добавьте в текст запроса ПЕРВЫЕ 1 после слова ВЫБРАТЬ, затем в коде: если Выборка.Следующий() — значит, строка есть и её поля доступны. Это экономичнее, чем выгружать весь результат и брать нулевую строку таблицы.

Можно ли обратиться к полю выборки, если имя заранее неизвестно?

Да, через коллекцию колонок результата: РезультатЗапроса.Колонки содержит описания полей, а к значению в таблице значений можно обратиться по имени колонки как строке — Строка[ИмяКолонки]. Это используется в универсальных обработках произвольных запросов.

Что быстрее: обход выборки или выгрузка в таблицу значений?

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

Итог

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

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