При разработке отчетов в Системе компоновки данных (СКД) программисты часто сталкиваются с необходимостью реализовать поиск по строковой маске. Стандартный оператор ПОДОБНО в языке запросов 1С отлично справляется с этой задачей, когда маска задана жестко, но работа с динамическими параметрами, которые вводит пользователь, имеет свои нюансы. В этой статье мы подробно разберем, как правильно реализовать поиск по части строки, избежать ошибок совместимости типов и обеспечить высокую производительность отчета.
Рассмотрим типичную ситуацию: разработчик пытается написать условие в запросе СКД следующим образом:
ГДЕ Контрагент.Наименование ПОДОБНО &Наименование + "%"
Проанализируем, почему такой подход может не сработать или вызвать ошибку. Во-первых, система компоновки данных — это не просто транслятор запроса, а сложный механизм, который самостоятельно управляет параметрами. Во-вторых, выполнение строковых операций (склеивания) непосредственно в секции ГДЕ может привести к ошибкам на стороне СУБД (например, MS SQL Server или PostgreSQL), особенно если типы данных параметра и поля в таблице различаются (например, неограниченная строка и строка фиксированной длины). На некоторых версиях платформы, например 8.3.18, это может вызывать исключение.
Самым правильным и надежным способом в СКД является вынос логики формирования маски поиска в настройки параметров компоновки. Давайте разберем этот метод по шагам:
&Наименование, который заполняет пользователь.
"%" + &Наименование + "%"
В тексте самого запроса при этом мы оставляем максимально простую конструкцию:
ГДЕ Контрагент.Наименование ПОДОБНО &Наименование
Почему это работает лучше? Когда мы используем колонку Выражение, вычисление строки происходит средствами встроенного языка 1С до того, как запрос будет отправлен на сервер базы данных. В СУБД передается уже готовая строка маски (например, "%Газпром%"), что исключает конфликты типов при конкатенации в SQL-запросе.
Часто требуется, чтобы условие поиска применялось только тогда, когда пользователь действительно заполнил поле поиска. Рассмотрим ситуацию, когда мы используем расширение языка запросов СКД — фигурные скобки. Проанализируем пример кода:
{ГДЕ (Контрагенты.Наименование ПОДОБНО &Наименование)}
Если мы просто подставим &Наименование, и пользователь его не заполнит, СКД может исключить это условие из итогового запроса. Однако, если у нас настроено выражение "%" + &Наименование + "%", параметр технически всегда будет заполнен (как минимум, символами процента). Чтобы отчет не "тормозил", пытаясь найти все записи по маске "%%", мы можем усложнить выражение в параметрах:
ВЫБОР
КОГДА &Наименование = "" ИЛИ &Наименование ЕСТЬ NULL
ТОГДА ""
ИНАЧЕ "%" + СократитьП(&Наименование) + "%"
КОНЕЦ
Такой подход позволяет корректно обрабатывать пустые значения и автоматически удалять лишние пробелы, которые пользователь мог случайно ввести.
Разберем важный технический аспект — использование индексов СУБД (SARGability). Посмотрим на два варианта формирования маски:
&Наименование + "%". В этом случае, если по полю Наименование есть индекс, СУБД сможет его использовать. Поиск будет выполняться мгновенно даже в миллионных списках."%" + &Наименование + "%". Если маска начинается с символа процента, индекс использовать невозможно. СУБД будет вынуждена прочитать всю таблицу (Full Table Scan), что значительно замедлит формирование отчета при больших объемах данных.Рекомендуем всегда уточнять у бизнес-аналитиков, действительно ли им нужен поиск «везде» или достаточно поиска «с начала строки».
Выясним причину, по которой поиск может выдавать неверные результаты, если в названии контрагента встречаются сами символы %, _ или [. Например, нам нужно найти строку "Скидка 10%". Если мы просто передадим ее в ПОДОБНО, символ % будет воспринят как маска любого количества символов.
Для решения этой задачи в языке запросов предусмотрено ключевое слово СПЕЦСИМВОЛ. Рассмотрим пример реализации:
#):
СтрЗаменить(СтрЗаменить(&Наименование, "%", "#%"), "_", "#_") + "%"
ГДЕ Контрагент.Наименование ПОДОБНО &Наименование СПЕЦСИМВОЛ "#"
Это гарантирует, что введенные пользователем знаки процента будут восприняты как обычный текст, а не как команды поиска.
Проанализируем ситуацию с ошибками на новых версиях платформы (8.3.18 и выше). Одной из частых причин сбоев является тип параметра Строка (неограниченной длины). В SQL-запросах такие поля часто транслируются в типы типа NVARCHAR(MAX) или TEXT, которые имеют ограничения на использование в некоторых операциях сравнения и конкатенации.
Практический совет: Всегда устанавливайте для строковых параметров поиска фиксированную длину (например, 150 или 250 символов) на вкладке параметров СКД. Это упрощает работу оптимизатора запросов СУБД и предотвращает ошибки несовместимости типов.
Посмотрим на поведение отчета в разных средах. Если ваша база работает на PostgreSQL, поиск через ПОДОБНО может быть чувствителен к регистру (в отличие от MS SQL Server, где настройки базы обычно позволяют искать без учета регистра). Чтобы сделать поиск универсальным, приводите обе части условия к одному регистру:
ГДЕ ВРЕГ(Контрагент.Наименование) ПОДОБНО &НаименованиеВРегистре
При этом в выражении параметра &НаименованиеВРегистре обязательно используйте функцию ВРЕГ():
ВРЕГ("%" + СократитьП(&Наименование) + "%")
Подводя итог, можно сказать, что наиболее стабильный и профессиональный способ работы с ПОДОБНО в СКД — это использование вкладки Параметры для подготовки строки маски. Это позволяет избежать ошибок типов, реализовать сложную логику проверки заполнения и обеспечить корректную работу индексов базы данных.