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

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

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

Причина ошибки и правильный обход выборки

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


РезультатЗапроса = Запрос.Выполнить().Выбрать();
Пока Записи.Следующий() Цикл
    //Сообщить(Записи.??????????????);
КонецЦикла;

В данном случае метод Выбрать() возвращает объект ВыборкаИзРезультатаЗапроса и записывает его в переменную РезультатЗапроса. Однако в условии цикла Пока происходит обращение к несуществующей переменной Записи. Из-за этого платформа не может выполнить метод Следующий().

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

Разберем рабочий пример обхода:


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

Пока Выборка.Следующий() Цикл
    Сообщить(Выборка.ОС);
КонецЦикла;

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

Оптимизация запроса к виртуальной таблице остатков

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

Проанализируем правила передачи параметров в виртуальные таблицы:

  1. Передача типа данных для счета: В регистрах бухгалтерии поле Счет имеет тип ссылки (например, ПланСчетовСсылка.ЕПСБУ). Передавать числовое значение 106.11 нельзя. Ссылку необходимо получать через менеджер плана счетов: ПланыСчетов.ЕПСБУ.НайтиПоКоду("106.11").
  2. Использование параметров виртуальной таблицы: Фильтрацию по дате и счету необходимо производить на уровне самой виртуальной таблицы Остатки(&Дата, Счет = &Счет, , ), а не в секции ГДЕ. Это переносит расчеты на сторону СУБД.

Рассмотрим правильное формирование запроса с установкой параметров:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ЕПСБУОстатки.СуммаОстаток,
    |	ЕПСБУОстатки.Субконто2 КАК ОС
    |ИЗ
    |	РегистрБухгалтерии.ЕПСБУ.Остатки(&Дата, Счет = &Счет, , ) КАК ЕПСБУОстатки";

Счет106 = ПланыСчетов.ЕПСБУ.НайтиПоКоду("106.11");

Запрос.УстановитьПараметр("Дата", ТекущаяДата());
Запрос.УстановитьПараметр("Счет", Счет106);

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

Пока Выборка.Следующий() Цикл
    Сообщить("ОС: " + Выборка.ОС + ", Остаток: " + Выборка.СуммаОстаток);
КонецЦикла;

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

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

Посмотрим на пример обхода таблицы значений:


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

Для Каждого Стр Из ТаблицаДанных Цикл
    Сообщить(Стр.ОС);
КонецЦикла;

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

← На главную