При работе с языком запросов в 1С начинающие разработчики часто сталкиваются с ошибками при обходе результатов. Одной из самых распространенных проблем является несовпадение имени переменной, в которую сохраняется выборка, и переменной, используемой в цикле обработки. Рассмотрим, как правильно перебирать записи запроса, обращаться к реквизитам и избегать типичных ошибок.
Выясним причину проблемы, возникшей в исходном коде. Автор написал следующий фрагмент:
РезультатЗапроса = Запрос.Выполнить().Выбрать();
Пока Записи.Следующий() Цикл
//Сообщить(Записи.??????????????);
КонецЦикла;
В данном случае метод Выбрать() возвращает объект ВыборкаИзРезультатаЗапроса и записывает его в переменную РезультатЗапроса. Однако в условии цикла Пока происходит обращение к несуществующей переменной Записи. Из-за этого платформа не может выполнить метод Следующий().
Чтобы исправить ошибку и вывести значение псевдонима ОС из запроса, необходимо использовать единое имя переменной выборки и обращаться к полям через имя этой переменной.
Разберем рабочий пример обхода:
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.ОС);
КонецЦикла;
В этом коде метод Выборка.Следующий() последовательно переходит к следующей записи в выборке. Пока записи существуют, метод возвращает значение Истина и цикл продолжается. Внутри цикла доступ к колонкам выборки осуществляется по их именам или псевдонимам, заданным в запросе (например, Выборка.ОС или Выборка.СуммаОстаток).
Обратим внимание на сам текст запроса. Обращение к виртуальной таблице без указания параметров (РегистрБухгалтерии.ЕПСБУ.Остатки(, , , )) вынуждает систему рассчитывать остатки по абсолютно всем счетам и субконто регистра. Это приводит к существенному снижению производительности.
Проанализируем правила передачи параметров в виртуальные таблицы:
Счет имеет тип ссылки (например, ПланСчетовСсылка.ЕПСБУ). Передавать числовое значение 106.11 нельзя. Ссылку необходимо получать через менеджер плана счетов: ПланыСчетов.ЕПСБУ.НайтиПоКоду("106.11").Остатки(&Дата, Счет = &Счет, , ), а не в секции ГДЕ. Это переносит расчеты на сторону СУБД.Рассмотрим правильное формирование запроса с установкой параметров:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЕПСБУОстатки.СуммаОстаток,
| ЕПСБУОстатки.Субконто2 КАК ОС
|ИЗ
| РегистрБухгалтерии.ЕПСБУ.Остатки(&Дата, Счет = &Счет, , ) КАК ЕПСБУОстатки";
Счет106 = ПланыСчетов.ЕПСБУ.НайтиПоКоду("106.11");
Запрос.УстановитьПараметр("Дата", ТекущаяДата());
Запрос.УстановитьПараметр("Счет", Счет106);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить("ОС: " + Выборка.ОС + ", Остаток: " + Выборка.СуммаОстаток);
КонецЦикла;
Если полученные данные планируется использовать неоднократно, передавать в другие процедуры или выполнять над ними дополнительную сортировку в коде, результат запроса можно выгрузить в таблицу значений с помощью метода Выгрузить().
Посмотрим на пример обхода таблицы значений:
РезультатЗапроса = Запрос.Выполнить();
ТаблицаДанных = РезультатЗапроса.Выгрузить();
Для Каждого Стр Из ТаблицаДанных Цикл
Сообщить(Стр.ОС);
КонецЦикла;
Важно: Метод Выгрузить() сразу помещает весь объем полученных данных в оперативную память. Если ожидается выборка из десятков тысяч строк, рекомендуется использовать последовательный обход через Выбрать() и метод Следующий(), так как он считывает данные порциями и снижает нагрузку на память сервера.