Почему не работает выборка в запросе по реквизиту с формы и как исправить ошибку несоответствия типов?

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

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

Анализ исходной проблемы: почему выборка пустая?

Рассмотрим ситуацию: на форме расположено поле ввода ПолеВвода1, в котором пользователь выбирает сотрудника из справочника. Далее в коде значение из этого поля передается в параметр запроса для фильтрации данных по наименованию. Проанализируем исходный программный код, который вызвал затруднения:


Процедура КнопкаВыполнитьНажатие(Кнопка)
    Наименование = ПолеВвода1; // Здесь кроется первая ошибка
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |    Сотрудники.Код КАК Код,
        |    Сотрудники.Ссылка КАК Ссылка
        |ИЗ
        |    Справочник.Сотрудники КАК Сотрудники
        |ГДЕ
        |    Сотрудники.Наименование = &Наименование"; 
    Запрос.УстановитьПараметр("Наименование", Наименование);
    
    РезультатЗапроса = Запрос.Выполнить();
    ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
    
    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
        Сообщить(ВыборкаДетальныеЗаписи.Код);
    КонецЦикла;
КонецПроцедуры

На первый взгляд код выглядит логично, однако он не работает. Основная причина заключается в несоответствии типов данных. Выясним подробности: если ПолеВвода1 связано с реквизитом типа СправочникСсылка.Сотрудники, то при присваивании Наименование = ПолеВвода1 переменная Наименование получает значение типа Ссылка, а не текстовую строку. В тексте запроса же происходит сравнение поля Сотрудники.Наименование (которое является строкой) с параметром &Наименование (в который передана ссылка).

В языке запросов 1С сравнение разных типов данных всегда дает результат Ложь. Система не пытается неявно превратить ссылку в текст. В итоге условие ГДЕ не выполняется ни для одной записи, и запрос возвращает пустой результат.

Разбор поведения отладчика и «Ошибки чтения значения»

Рассмотрим еще один важный момент, упомянутый в обсуждении — появление сообщения «ошибка чтения значения» в окне отладчика при просмотре переменной ВыборкаДетальныеЗаписи. Посмотрим на причины этого явления:

  1. Метод Следующий() не вызван: Объект выборки после создания находится в состоянии «перед первой записью». Поля выборки (такие как Код или Ссылка) недоступны для чтения, пока не будет успешно выполнен метод Следующий().
  2. Пустой результат запроса: Если запрос не нашел ни одной записи, метод Следующий() сразу вернет значение Ложь, и цикл Пока не начнется. При попытке принудительно вычислить значение полей выборки в Табло отладчика, система выдаст ошибку, так как текущей записи не существует.
  3. Особенности файловой базы: В файловом режиме отладчик иногда более жестко реагирует на обращение к свойствам объектов, которые еще не инициализированы данными.

Для корректной проверки данных в отладчике рекомендуется сначала проверить свойство РезультатЗапроса.Пустой(). Это даст однозначный ответ: есть ли данные для обработки или проблема в самом запросе.

Варианты решения проблемы

Рассмотрим два пути исправления ситуации, в зависимости от того, что именно мы хотим получить.

Вариант №1: Сравнение по ссылке (Рекомендуемый)

Если у нас уже есть ссылка на сотрудника из поля ввода, правильнее и быстрее искать в базе именно по этой ссылке. Посмотрим, как изменится код:


// В поле ввода у нас Ссылка, передаем ее как есть
Запрос.Текст = 
    "ВЫБРАТЬ
    |    Сотрудники.Код КАК Код
    |ИЗ
    |    Справочник.Сотрудники КАК Сотрудники
    |ГДЕ
    |    Сотрудники.Ссылка = &СотрудникСсылка"; 

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

Преимущество этого способа: поиск по ссылке (индексу) работает максимально быстро. К тому же, это исключает ошибки, если в базе есть два сотрудника с одинаковыми именами.

Вариант №2: Сравнение по наименованию

Если по какой-то причине нам принципиально нужно искать именно по строке (например, для поиска однофамильцев), нам необходимо явно получить строку из ссылки. Проанализируем изменения:


// Получаем строковое представление из объекта ссылки
НаименованиеСтрокой = ПолеВвода1.Наименование; 

Запрос.Текст = 
    "ВЫБРАТЬ
    |    Сотрудники.Код КАК Код
    |ИЗ
    |    Справочник.Сотрудники КАК Сотрудники
    |ГДЕ
    |    Сотрудники.Наименование = &Наименование"; 

Запрос.УстановитьПараметр("Наименование", НаименованиеСтрокой);

В этом случае в параметр &Наименование попадет именно текст (например, "Иванов Иван Иванович"), и сравнение в запросе отработает корректно.

Практические советы для работы с запросами

Чтобы избежать подобных трудностей в будущем, проанализируем несколько рекомендаций:

Таким образом, мы выяснили, что внимательное отношение к типам данных и понимание механизмов работы отладчика 1С позволяют быстро локализовать и устранить ошибки в запросах. Помните, что Ссылка и Наименование (строка) — это разные сущности, и их правильное использование — залог стабильной работы системы.

← На главную