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