Почему запрос в консоли 1С выполняется, а в коде внешнего отчета возвращает пустой результат?

Программист 1С v8.3 (Обычные формы) 1С:Зарплата и Управление Персоналом Управленческий учет
← На главную

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

Разбираем основную причину: несоответствие типов параметров

Проанализируем ситуацию, описанную в теме. Как подтвердил автор, в 99% случаев проблема кроется в типах передаваемых параметров. В консоли запросов мы часто выбираем значения интерактивно, и консоль сама подставляет нужную ссылку. В коде же мы можем совершить неочевидные ошибки. Рассмотрим их:

  1. Сотрудники vs Физические лица. Это самая частая ошибка при работе с кадровыми регистрами. Регистр СостояниеРаботниковОрганизаций обычно хранит данные в разрезе справочника Сотрудники. Если в программном коде в параметр &сотруд передана ссылка на справочник ФизическиеЛица, запрос выполнится без ошибок, но результат будет пустым, так как типы не совпадают.
  2. Перечисления. При установке параметров типа Перечисление важно использовать полное обращение. Например, Перечисления.ВидыЗанятостиВОрганизации.ОсновноеМестоРаботы. Если значение передается из реквизита формы, необходимо убедиться, что тип этого реквизита в метаданных в точности совпадает с ожидаемым типом в регистре.
  3. Пустые ссылки. Проверим ситуацию, когда параметр передается как Неопределено или пустая ссылка соответствующего типа. Запрос в консоли может быть настроен на конкретного сотрудника, а в коде из-за ошибки в логике в параметр попадает пустое значение.

Анализ кода и работа с выборкой

Посмотрим на пример кода, который вызывал затруднения. Разберем фрагмент функции, где выполняется запрос к срезу последних:


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

ЗапросБольничныйСрезПоследних.УстановитьПараметр("дата", НачПериода);
ЗапросБольничныйСрезПоследних.УстановитьПараметр("сотруд", Сотр);

РезультатЗапросаБольн = ЗапросБольничныйСрезПоследних.Выполнить().Выбрать();

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


ТаблицаРезультата = ЗапросБольничныйСрезПоследних.Выполнить().Выгрузить();
// Здесь в отладчике можно посмотреть количество строк в ТаблицаРезультата

Особенности работы с датами и виртуальными таблицами

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

  1. Граница времени. Если запись в регистре была сделана в ту же секунду, которая передана в параметр &дата, она может не попасть в срез. Для получения гарантированного результата на конец дня или конкретный момент времени используем объект Граница:
    
    ГраницаПериода = Новый Граница(КонецДня(НачПериода), ВидГраницы.Включая);
    Запрос.УстановитьПараметр("дата", ГраницаПериода);
    
  2. Начало дня vs Конец дня. Часто в консоли мы пишем дату «01.02.2018», и консоль интерпретирует это как 01.02.2018 00:00:00. Если в программном коде мы передаем переменную, содержащую дату с временем (например, текущую дату сеанса), результаты могут отличаться. Рекомендуется всегда приводить даты к началу или концу дня с помощью функций НачалоДня() или КонецДня().

Проблема избыточных условий и RLS

Проанализируем ситуацию, когда в коде используются дополнительные фильтры. В сообщении 23 упоминается избыточность условий. Если мы фильтруем и по сотруднику, и по его виду занятости через точку (Сотрудник.ВидЗанятости = &ВидЗанятости), это может замедлить запрос или привести к пустому результату, если у данного сотрудника в справочнике указан иной вид занятости, чем мы ожидаем.

Также нельзя забывать про RLS (Row Level Security). Если отчет запускается под пользователем с ограниченными правами, система автоматически добавит условия в ГДЕ, ограничивая доступ к записям по организациям или подразделениям. Консоль запросов часто запускается под «Полными правами», что и создает иллюзию «работающего» запроса, который «ломается» в отчете у обычного бухгалтера.

Рекомендации по поиску ошибок

Если вы столкнулись с подобной проблемой, выполните следующие шаги:

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

Таким образом, успех выполнения запроса в коде зависит от чистоты типизации данных и понимания того, как платформа работает с границами периодов и правами доступа. Внимательная проверка типов параметров через отладчик — это кратчайший путь к исправлению данной ошибки.

← На главную