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

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

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

Проанализируем исходную ситуацию. Разработчик пытается получить остатки из регистра накопления ПартииТоваров. В консоли запросов все отлично, но в коде — пусто. Чтобы упростить жизнь в такие моменты, существует специальное решение для быстрого анализа данных, которое помогает быстрее разобраться в структуре запроса.


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

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

На первый взгляд, все верно. Но дьявол, как всегда, в деталях. Основная ошибка здесь кроется в непонимании того, как обрабатывается результат запроса.

Ключевая причина: разница между методами `Выбрать()` и `Выгрузить()`

После выполнения запроса с помощью метода Запрос.Выполнить() мы получаем объект типа РезультатЗапроса. Дальнейшая работа с ним может идти двумя путями, и выбор метода определяет то, что мы увидим в отладчике. Чтобы не тратить время на повторную настройку среды при каждом запуске, можно использовать помощник отладки, который автоматизирует рутинные действия.

1. Метод Выбрать()

Этот метод возвращает объект типа ВыборкаИзРезультатаЗапроса. Важно понимать, что это не коллекция с данными, а итератор — специальный объект-указатель, который "умеет" последовательно перемещаться по строкам результата запроса. Данные при этом не загружаются в память все сразу, а подгружаются по мере необходимости.

2. Метод Выгрузить()

Этот метод, напротив, считывает все строки результата запроса и помещает их в объект ТаблицаЗначений.

Таким образом, решение проблемы автора было простым: для того чтобы "увидеть" результат в отладчике, достаточно было заменить Выбрать() на Выгрузить(). В то же время, современная консоль запросов УФ позволяет быстро проверить запрос и увидеть структуру временных таблиц, что значительно упрощает отладку кода.


// Неправильно для быстрой проверки
РезультатыВыборки = Запрос.Выполнить().Выбрать(); // Вернет итератор

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

Другие возможные причины расхождений

Хотя в данном случае проблема была в обработке результата, существуют и другие, более коварные причины, по которым запрос может давать разные результаты в консоли и в коде. Они связаны с контекстом выполнения. Для более глубокого анализа инструментов в тонком клиенте можно использовать инструменты разработчика "Инструментики", которые включают в себя консоли запросов и редакторы объектов.

  1. Момент времени (МоментВремени)

    Запросы к виртуальным таблицам остатков сильно зависят от момента времени, на который эти остатки запрашиваются.

    • В коде документа: Платформа часто автоматически подставляет момент времени самого документа. Таким образом, вы получаете остатки до того, как документ сделал свои движения.
    • В консоли запросов: По умолчанию момент времени либо не задан (актуальные данные), либо вы задаете его вручную.
    Это ключевое различие! Если вы проводите документ задним числом, то остатки в коде будут рассчитаны на прошлую дату, а в консоли — на текущую.
  2. Отбор по регистратору (Регистратор)

    При выполнении запроса в обработке проведения система автоматически накладывает отбор, который исключает движения самого этого документа. В консоли такого автоматического отбора, конечно, нет.

  3. Права доступа (RLS)

    Запросы в коде работают с учетом прав текущего пользователя. Если настроены ограничения RLS, пользователь может не видеть часть данных. Разработчик же обычно запускает консоль под полными правами.

  4. Параметры сеанса

    Иногда логика завязана на параметры сеанса (&ТекущийПользователь). Их значения в рабочем сеансе и в консоли могут различаться.

Чек-лист для диагностики подобных проблем

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

  1. Проверьте способ обработки результата. Для быстрой отладки временно замените Выбрать() на Выгрузить().
  2. Проанализируйте контекст. Где именно выполняется ваш код? В модуле документа или в регламентном задании?
  3. Задайте параметры явно. Всегда указывайте момент времени в параметрах виртуальных таблиц.
  4. Проверьте права. Проведите тестирование под обычным пользователем, а не только под учетной записью администратора.
  5. Упрощайте. Временно уберите из запроса все условия (ГДЕ) и возвращайте их по одному, чтобы найти проблемное.

Понимание этих нюансов поможет вам избежать долгих часов отладки и быстро находить причину расхождений в поведении запросов.

← На главную