Почему результат запроса в отладке не совпадает с результатом в консоли запросов 1С

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

В процессе разработки и отладки программного кода в 1С разработчики нередко сталкиваются с ситуацией, когда один и тот же текст запроса с одинаковыми на первый взгляд параметрами возвращает разное количество строк или разные значения в отладчике (при выполнении кода) и в консоли запросов.

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

Главная причина: различие между данными в памяти и базами данных

Запрос в 1С всегда обращается к таблицам базы данных на сервере СУБД. Если запрос выполняется по ссылке документа или справочника (например, через условие ГДЕ ТаблицаТовары.Ссылка = &Ссылка), он считывает только те данные, которые фактически записаны и зафиксированы в базе.

Если в процессе обработки проведения или выполнения алгоритма в модуле объекта были изменены значения в табличной части (например, изменен реквизит ВариантОбеспечения или признак Отменено), но вызов метода Записать() еще не произошел или изменения не зафиксированы в базе, возникает следующее расхождение:

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

Практический анализ ситуации из кода

Проанализируем фрагмент запроса, используемый при формировании движений документа ЗаказКлиента:


Запрос.Текст = "";
Для Каждого ТекстЗапроса Из ТекстыЗапроса Цикл
    Запрос.Текст = Запрос.Текст + ТекстЗапроса.Значение;
КонецЦикла;

Результат = Запрос.ВыполнитьПакет();

Для Каждого ТекстЗапроса Из ТекстыЗапроса Цикл
    ИмяТаблицы = ТекстЗапроса.Представление;
    Если Не ПустаяСтрока(ИмяТаблицы) Тогда
        Индекс = ТекстыЗапроса.Индекс(ТекстЗапроса);
        Таблицы.Вставить(ИмяТаблицы, Результат[Индекс].Выгрузить());
    КонецЕсли;
КонецЦикла;

Рассмотрим отбор во вложенном запросе пакета, где проверяются условия по табличной части документа:


ГДЕ
    ТаблицаТовары.Ссылка = &Ссылка
    И (НЕ ТаблицаТовары.Отменено)
    И ТаблицаТовары.ВариантОбеспечения В (
        ЗНАЧЕНИЕ(Перечисление.ВариантыОбеспечения.Отгрузить),
        ЗНАЧЕНИЕ(Перечисление.ВариантыОбеспечения.ОтгрузитьОбособленно)
    )
    И &Статус В (
        ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказовКлиентов.КОбеспечению),
        ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказовКлиентов.КОтгрузке),
        ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказовКлиентов.Закрыт)
    )

В данном случае в консоли запросов значение реквизита ВариантОбеспечения в базе данных было установлено как Не обеспечивать, из-за чего строки отсекались фильтром. В то же время во время выполнения документа в отладчике реквизиты табличной части перед выполнением запроса программно пересчитывались и устанавливались в значение Отгрузить. Это и приводило к разнице в количестве итоговых строк.

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

Помимо несохраненных изменений в объекте, разберем другие факторы, которые могут вызывать расхождение результатов отладки и консоли запросов:

  1. Права доступа и RLS (Restriction at Row Level): В коде на сервере запрос может выполняться в привилегированном режиме с помощью метода УстановленПривилегированныйРежим(), опускающего проверки RLS. В консоли запросов отбор по правам текущего пользователя продолжает действовать.
  2. Контекст транзакции: Если перед вызовом запроса в текущей транзакции были сделаны записи в физические таблицы (например, движения по регистрам), запрос в коде увидит эти данные. Консоль запросов, запущенная в отдельном сеансе, не имеет доступа к нефиксированной (uncommitted) транзакции.
  3. Несоответствие типов параметров: Передача значения типа Неопределено вместо пустой ссылки конкретного справочника (например, Справочники.Номенклатура.ПустаяСсылка()) или передача объекта Граница вместо типа Дата в виртуальные таблицы остатков.
  4. Использование внешнего менеджера временных таблиц: Если объект Запрос использует предварительно заполненный МенеджерВременныхТаблиц, выполнение отдельного фрагмента в консоли без наполнения временных таблиц даст пустой результат.

Алгоритм диагностики и решения проблемы

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

  1. Проверить типы всех передаваемых параметров в коде с помощью функции ТипЗнч(&ИмяПараметра) непосредственно перед вызовом метода Запрос.Выполнить().
  2. Убедиться, что объект сохранен в базе данных и его табличные части в памяти совпадают с записанными данными.
  3. Проверить, не меняются ли реквизиты объекта или строки табличных частей непосредственно в обработчиках ПередЗаписью или ОбработкаПроведения перед вызовом запросов.
  4. Если запрос использует временные таблицы, проверить содержимое таблиц через выражение отладчика: Запрос.МенеджерВременныхТаблиц.ПолучитьДанные("ИмяВременнойТаблицы").Выгрузить().
  5. Проверить значение функции УстановленПривилегированныйРежим() в точке выполнения запроса.
← На главную