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