Почему возникает «ошибка чтения значения» при работе с выборкой запроса в 1С и как её исправить?

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

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

Выясним причину возникновения ошибки

Объект ВыборкаИзРезультатаЗапроса работает как последовательный курсор. В момент выполнения метода Запрос.Выполнить().Выбрать() платформа создает объект выборки, но сам курсор позиционирован до первой строки результата.

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

Основные причины, по которым возникает эта проблема:

  1. Отсутствие вызова метода позиционирования: Код пытается прочитать реквизиты выборки до первого вызова метода Следующий().
  2. Пустой результат запроса: Если запрос не вернул ни одной строки (например, передан пустой или некорректный параметр &Ссылка), первый же вызов метода Следующий() возвращает Ложь, и курсор остается непозиционированным.
  3. Ограничения прав на уровне записей (RLS): Запрос в консоли запросов чаще всего запускается с полными правами. В рабочем сеансе на сервере могут действовать RLS для таблицы справочника или табличной части, из-за чего выборка оказывается пустой.

Разберем правильный обход выборки

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


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

Запрос.УстановитьПараметр("Ссылка", Данные.Отправитель);

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

Если запрос гарантированно должен вернуть только одну строку (например, используется конструкция ВЫБРАТЬ ПЕРВЫЕ 1), циклическая конструкция не требуется, но проверить наличие строки через условный оператор Если необходимо:


Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
    // Курсор успешно перешел на первую строку
    ЗначениеИНН = Выборка.ИНН;
Иначе
    // Данные не найдены, обработка ситуации
КонецЕсли;

Проанализируем альтернативные способы работы с результатом

1. Предварительная проверка результата на пустоту

Перед тем как формировать выборку, мы можем проверить, содержит ли результат запроса записи вообще, используя метод Пустой() объекта РезультатЗапроса:


РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
    Выборка = РезультатЗапроса.Выбрать();
    Выборка.Следующий();
    ЗначениеИНН = Выборка.ИНН;
КонецЕсли;

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

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


ТаблицаРезультата = Запрос.Выполнить().Выгрузить();
Если ТаблицаРезультата.Количество() > 0 Тогда
    СтрокаДанных = ТаблицаРезультата[0];
    ЗначениеИНН = СтрокаДанных.ИНН;
КонецЕсли;

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

← На главную