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