При разработке отчетов на Системе компоновки данных (СКД) начинающие программисты часто сталкиваются с ситуацией, когда отчет отлично работает при заполнении всех параметров, но выдает ошибку, если пользователь оставляет одно из полей пустым. Особенно остро эта проблема проявляется при попытке реализовать логику «ИЛИ» между двумя параметрами (например, фильтрация либо по складу, либо по номенклатуре) непосредственно в тексте запроса.
В этой статье мы подробно разберем, почему стандартный подход с использованием фигурных скобок может давать сбой, проанализируем механизм работы расширения языка запросов СКД и рассмотрим несколько эффективных способов решения данной задачи.
Рассмотрим ситуацию, с которой столкнулся автор темы. В запросе к виртуальной таблице остатков и оборотов было прописано следующее условие:
ВЫБРАТЬ
ОстаткиПоСериямОстаткиИОбороты.Серия,
ОстаткиПоСериямОстаткиИОбороты.Номенклатура,
ОстаткиПоСериямОстаткиИОбороты.Склад
ИЗ
РегистрНакопления.ОстаткиПоСериям.ОстаткиИОбороты(
{(&НачалоПериода)},
{(&КонецПериода)},
Авто, ,
{(Склад = &Склад ИЛИ Номенклатура = &Номенклатура)}
) КАК ОстаткиПоСериямОстаткиИОбороты
Проанализируем причину ошибки. Когда мы заключаем условие в фигурные скобки {}, мы говорим системе компоновки: «этот блок кода должен быть включен в итоговый запрос только в том случае, если соответствующие параметры заполнены пользователем». Однако, объединяя два параметра через ИЛИ внутри одних фигурных скобок, мы создаем единый неделимый блок.
Если пользователь заполняет только «Номенклатуру», СКД видит, что один из параметров внутри блока активирован, и пытается подставить в итоговый SQL-запрос всю конструкцию: (Склад = &Склад ИЛИ Номенклатура = &Номенклатура). Но так как параметр &Склад не был инициализирован (не выбран пользователем), система не может корректно сформировать запрос к базе данных, что и приводит к ошибке выполнения.
Самый простой и правильный способ сделать параметры необязательными в СКД — это вынести каждое условие в отдельные фигурные скобки. В этом случае система будет обрабатывать их независимо друг от друга. Если заполнен только один параметр, в запрос попадет только одно условие.
Изменим запрос в параметрах виртуальной таблицы следующим образом:
ГДЕ
{(Склад = &Склад)}
И {(Номенклатура = &Номенклатура)}
Важный нюанс: при таком подходе условия будут соединяться по логическому «И». Если пользователю требуется именно логика «ИЛИ» (показать движения либо по конкретному складу, либо по конкретному товару), этот метод не подойдет в чистом виде, так как СКД не умеет динамически менять И на ИЛИ между разными блоками расширения запроса.
Если нам критически важно сохранить проверку параметров именно через ИЛИ и при этом избежать ошибок при пустых значениях, можно воспользоваться проверкой на пустую ссылку. Выясним, как это реализовать прямо в тексте запроса.
Мы можем написать условие, которое будет проверять, заполнено ли значение параметра. Если параметр пуст, условие всегда будет возвращать ИСТИНА, тем самым не влияя на результат выборки.
{ (ВЫБОР
КОГДА &Склад <> ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка)
ТОГДА Склад = &Склад
ИНАЧЕ ИСТИНА
КОНЕЦ
ИЛИ
ВЫБОР
КОГДА &Номенклатура <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
ТОГДА Номенклатура = &Номенклатура
ИНАЧЕ ИСТИНА
КОНЕЦ) }
Рассмотрим подробнее, как это работает. Даже если блок в фигурных скобках активируется, конструкция ВЫБОР корректно обрабатывает пустые значения параметров, подставляя ИСТИНА вместо фильтрации. Однако помните, что использование сложных логических конструкций в параметрах виртуальных таблиц может негативно сказаться на производительности (плане выполнения запроса в СУБД).
Для программиста на 1С наиболее «чистым» и рекомендуемым способом является использование стандартного механизма отборов компоновки данных. Вместо того чтобы вручную прописывать параметры в тексте запроса, мы можем положиться на механизм Автозаполнение.
&Склад и &Номенклатура из текста запроса и из параметров виртуальной таблицы.При таком подходе СКД сама проанализирует запрос. Если в запросе используется виртуальная таблица, система автоматически применит выбранные пользователем фильтры максимально эффективно — передаст их в параметры виртуальной таблицы базы данных. Это исключает риск возникновения синтаксических ошибок при незаполнении полей.
Проанализируем еще один технический момент, упомянутый в обсуждении. В СКД существует разница между пустой ссылкой конкретного типа и значением Неопределено.
Если в настройках схемы на вкладке «Параметры» у параметра не задан тип или не указано начальное значение, то при открытии отчета там может находиться Неопределено. Сравнение СправочникСсылка = Неопределено в запросе может вести себя непредсказуемо или вызывать ошибку. Поэтому:
СправочникСсылка.Номенклатура).Подводя итог, для создания надежного отчета в 1С 8.3 рекомендуется:
ИЛИ внутри одной пары фигурных скобок {}.ВЫБОР КОГДА с проверкой на пустую ссылку, предварительно задав типы параметров в схеме.Соблюдение этих правил позволит создавать гибкие отчеты, которые не «падают» при попытке пользователя выполнить фильтрацию по неполным данным.