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