В процессе разработки отчетов на базе Системы компоновки данных (СКД) программисты иногда сталкиваются с парадоксальной ситуацией: поиск по точному соответствию (виду сравнения Равно) работает безупречно, а поиск по части строки (вид сравнения Содержит) не возвращает ни одной записи. При этом в консоли запросов аналогичный запрос с оператором ПОДОБНО отрабатывает корректно. Разберем эту проблему подробно, проанализируем причины ее возникновения и найдем способы решения.
Для начала проанализируем, как СКД трансформирует наши настройки в итоговый запрос. Одной из ключевых особенностей СКД является генерация макета компоновки данных, который содержит уже «раскрашенный» запрос с подставленными параметрами. В рассматриваемом случае, если заглянуть в макет (как показано в сообщении №7), можно увидеть странную картину. Вместо того чтобы подставить реальное значение, которое ввел пользователь, система формирует структуру следующего вида:
<parameterValue>
<name>П</name>
<value xsi:type="xs:string">%ПараметрыДанных.СтрокаПоиска%</value>
</parameterValue>
Здесь мы видим корень проблемы: СКД восприняла обращение к параметру ПараметрыДанных.СтрокаПоиска не как к объекту, содержащему значение, а как к обычной текстовой строке. В итоге в SQL-сервер уходит команда искать в базе данных буквально текст "%ПараметрыДанных.СтрокаПоиска%". Естественно, номенклатуры с таким наименованием в базе не существует, и поиск не дает результатов.
Чтобы окончательно убедиться в причинах сбоя, проанализируем данные, которые 1С отправляет на сторону СУБД. При использовании SQL Profiler (для клиент-серверного варианта) или средств отладки можно увидеть следующий исполняемый код:
exec sp_executesql N'SELECT
T1._Description
FROM dbo._Reference47 T1
WHERE (T1._Description LIKE P1 ESCAPE ''/'')', N'P1 nvarchar(4000)', N'%ПараметрыДанных.СтрокаПоиска%'
Сравним это с тем, как отрабатывает условие Равно:
exec sp_executesql N'SELECT
T1._Description
FROM dbo._Reference47 T1
WHERE (T1._Description = P1)', N'P1 nvarchar(4000)', N'мука'
Как мы видим, во втором случае платформа передает значение 'мука', а в первом — строковую «заглушку». Это подтверждает, что механизм компоновки макета на определенном этапе допускает ошибку интерпретации типов данных. Выясним, как это исправить.
Рассмотрим наиболее надежный способ решения этой проблемы — явное управление формированием строки поиска. Вместо того чтобы полагаться на автоматический вид сравнения Содержит в настройках отчета, мы можем подготовить параметр самостоятельно. Посмотрим на алгоритм действий:
СтрокаПоиска).П), в колонке Выражение пропишем формирование шаблона LIKE.Выражение должно выглядеть следующим образом:
"%" + &СтрокаПоиска + "%"
Важный момент: убедитесь, что тип данных параметра &СтрокаПоиска жестко задан как Строка, а не оставлен пустым или составным. Это исключит неоднозначность при приведении типов в процессе компоновки макета.
Проанализируем ситуацию с полем НаименованиеПолное. В большинстве типовых конфигураций (например, в 1C:Управление торговлей или 1С:ERP) это поле имеет неограниченную длину. Оператор ПОДОБНО в SQL может работать некорректно или крайне медленно с такими полями, особенно в файловом варианте базы данных.
Для оптимизации и исправления ошибок поиска рекомендуется использовать функцию ВЫРАЗИТЬ в тексте запроса СКД. Рассмотрим пример изменения запроса:
ВЫБРАТЬ
СправочникНоменклатура.Ссылка КАК Значение
ИЗ
Справочник.Номенклатура КАК СправочникНоменклатура
ГДЕ
ВЫРАЗИТЬ(СправочникНоменклатура.НаименованиеПолное КАК СТРОКА(1000)) ПОДОБНО &П
Такой подход не только делает поиск более предсказуемым для компоновщика, но и существенно ускоряет выполнение запроса на уровне СУБД, так как работа со строками фиксированной (пусть и большой) длины всегда эффективнее обработки объектов LOB (Large Objects).
Выясним еще одну возможную причину неудачи. Часто разработчики объединяют несколько условий в одну группу. Если в настройках СКД условия Равно и Содержит объединены по логическому И, поиск будет работать только тогда, когда введенная строка одновременно и полностью совпадает с наименованием, и содержит его. Это избыточно.
Проверим структуру отборов в настройках отчета:
Содержит, предварительно очистив кэш метаданных (удалить и заново добавить поле в набор данных СКД).В сообщении №7 упоминается конструкция СПЕЦСИМВОЛ "/". Это стандартный механизм 1С для поиска символов, которые сами по себе являются служебными в операторе LIKE (например, %, _, [). Однако в файловых базах реализация этого механизма иногда дает сбои. Если ваша строка поиска не содержит спецсимволов, попробуйте временно отключить использование ESCAPE в макете или переписать условие в запросе без него, чтобы исключить влияние этого фактора.
Мы проанализировали ситуацию, когда СКД подставляет имя параметра вместо его значения при поиске «Содержит». Основными методами решения являются явное формирование выражения параметра через конкатенацию символов %, ограничение длины строки через ВЫРАЗИТЬ и проверка корректности типов данных в схеме. Следуя этим рекомендациям, вы сможете настроить стабильный и быстрый поиск в ваших отчетах.