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