Условие «содержит» в языке запросов: шаблоны ПОДОБНО
Содержание
Условие «содержит» в языке запросов 1С задаётся оператором ПОДОБНО и шаблоном с процентами по краям: Поле ПОДОБНО "%текст%". Проценты слева и справа означают «любой набор символов — искомый фрагмент — любой набор символов», то есть поле содержит эту подстроку в любом месте.
Отдельной функции «Содержит» в языке запросов нет. Во встроенном языке есть СтрНайти, но в запросе её вызвать нельзя — отбор по вхождению подстроки делают именно через ПОДОБНО. Это работает для реквизитов типа «Строка»: наименований, комментариев, артикулов, номеров документов.
Один нюанс стоит держать в голове сразу: шаблон с процентом в начале ("%текст%" или "%текст") заставляет СУБД читать таблицу целиком. На справочнике в сотню элементов это незаметно, на документах за несколько лет — уже тормозит. Как этого избежать, разберём ниже.
Как устроен шаблон: проценты, подчёркивание и наборы
ПОДОБНО сравнивает значение поля с шаблоном. В шаблоне обычные символы означают сами себя, а несколько символов — специальные:
%— любое количество любых символов, в том числе ноль символов;_(подчёркивание) — ровно один любой символ;[абв]— один символ из перечисленного набора;[а-я]— один символ из диапазона;[^абв]— один символ, которого нет в наборе.
Отсюда три базовых сценария:
| Что нужно | Шаблон | Что найдёт |
|---|---|---|
| Содержит фрагмент | "%болт%" | «Болт М6», «Комплект болтов» |
| Начинается с фрагмента | "болт%" | «Болт М6», но не «Комплект болтов» |
| Заканчивается фрагментом | "%оцинк" | «Болт оцинк» |
Простейший запрос на вхождение подстроки:
ВЫБРАТЬ
Номенклатура.Ссылка,
Номенклатура.Наименование
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Наименование ПОДОБНО "%кабель%"
Запрос вернёт все элементы, в наименовании которых встречается «кабель» — и «Кабель ВВГ», и «Гофра для кабеля».
Подчёркивание удобно, когда известна структура строки. Шаблон "__-___" найдёт коды вида «АБ-123»: две буквы, дефис, три символа.
Как искать знак процента и подчёркивание в самом тексте
Проблема возникает, когда искомый фрагмент сам содержит % или _. Например, нужно найти номенклатуру со скидкой «30%». Шаблон "%30%%" сработает неправильно: второй % платформа примет за спецсимвол «любые символы», а не за знак процента.
Решение — объявить символ экранирования через ключевое слово СПЕЦСИМВОЛ. Символ, стоящий после него в шаблоне, теряет специальное значение:
ВЫБРАТЬ
Товары.Наименование
ИЗ
Справочник.Номенклатура КАК Товары
ГДЕ
Товары.Наименование ПОДОБНО "%30!%%" СПЕЦСИМВОЛ "!"
Разбор шаблона "%30!%%" при СПЕЦСИМВОЛ "!": % (любой текст) + 30 + !% (буквальный знак процента) + % (любой текст). Запрос найдёт любую строку, где встречается «30%».
В роли экранирующего можно взять любой символ, которого заведомо нет в данных — чаще всего это !, ~ или \. Чтобы найти буквальное подчёркивание, пишут "%!_%" с тем же СПЕЦСИМВОЛ "!".
Без СПЕЦСИМВОЛ экранировать нельзя — платформа просто не поймёт, что символ должен быть буквальным.
Как собрать шаблон в параметре из пользовательского ввода
В реальной задаче текст поиска вводит пользователь, а не прописан в запросе. Тогда в тексте запроса ставят параметр:
ВЫБРАТЬ
Контрагенты.Ссылка,
Контрагенты.Наименование
ИЗ
Справочник.Контрагенты КАК Контрагенты
ГДЕ
Контрагенты.Наименование ПОДОБНО &Шаблон СПЕЦСИМВОЛ "~"
А проценты добавляют уже в коде, при установке параметра:
Запрос.УстановитьПараметр("Шаблон", "%" + ЭкранироватьСпецсимволы(ТекстПоиска) + "%");
Пользовательский ввод обязательно экранируйте. Иначе, если человек введёт «50%», поиск поведёт себя непредсказуемо, а символ [ и вовсе может вызвать ошибку шаблона. Готовая функция экранирования:
Функция ЭкранироватьСпецсимволы(Текст)
// сначала экранируем сам символ экранирования
Результат = СтрЗаменить(Текст, "~", "~~");
Результат = СтрЗаменить(Результат, "%", "~%");
Результат = СтрЗаменить(Результат, "_", "~_");
Результат = СтрЗаменить(Результат, "[", "~[");
Возврат Результат;
КонецФункции
Порядок важен: экранирующий символ (~) обрабатываем первым, иначе вставленные позже ~% и ~_ экранируются повторно и ломаются.
Чем ПОДОБНО отличается от ПОДСТРОКА и других функций
В языке запросов есть строковые функции, но ищет вхождение только ПОДОБНО. Остальные решают смежные задачи:
ПОДСТРОКА(Строка, Начало, Длина)— вырезает кусок строки по позиции. Это не поиск: позицию нужно знать заранее.ВРЕГ(Строка)иНРЕГ(Строка)— приводят строку к верхнему или нижнему регистру.СОКРЛП(Строка)— убирает пробелы по краям.
Частая ошибка — попытаться вызвать в запросе СтрНайти или СтрДлина. Эти функции доступны только во встроенном языке, в тексте запроса их нет, и запрос с ними просто не выполнится.
Если фрагментов несколько и важно их взаимное расположение, их комбинируют. Например, «начинается на „АКТ“ и где-то дальше содержит „2024“»:
ГДЕ
Документ.Номер ПОДОБНО "АКТ%"
И Документ.Номер ПОДОБНО "%2024%"
Для поиска по большим текстовым полям (назначение платежа, длинные комментарии, содержимое присоединённых файлов) есть отдельный механизм — полнотекстовый поиск. Он работает по индексу, понимает словоформы и на объёмных данных в разы быстрее, чем ПОДОБНО "%…%". Включается в разделе Администрирование, а в коде используется объект ПолнотекстовыйПоиск. Для точного поиска подстроки в конкретном реквизите ПОДОБНО остаётся основным инструментом, для «найти упоминание» по всей базе — полнотекстовый поиск уместнее.
Когда для отбора лучше взять другое условие
ПОДОБНО — инструмент именно для поиска по фрагменту текста. Если задача другая, он только замедлит запрос и даст лишние совпадения.
- Точное значение известно. Ищете конкретный элемент справочника или перечисления — сравнивайте по ссылке через
=:Товар.Вид = &ВидТовара. Это быстро и однозначно. - Отбор по началу кода или номера. Если коды строго структурированы (например, все договоры филиала начинаются на «Ф-»), подойдёт шаблон по началу
"Ф-%"— но без ведущего процента, чтобы работал индекс. - Сравнение чисел и дат.
ПОДОБНОработает только со строками. Для дат и сумм используйтеМЕЖДУ,>=,<=— приводить их к строке и искать подстроку нельзя и не нужно. - Проверка на заполненность. Чтобы найти записи с непустым реквизитом, берите
Поле <> ""илиПоле <> NULL, а неПОДОБНО "%".
Хорошее правило: если во фрагменте нет неопределённости по позиции («где-то внутри строки»), то ПОДОБНО, скорее всего, лишний.
Регистр и буква «ё»: на что обратить внимание
В типовой поставке сравнение строк в запросе регистронезависимое. "%БОЛТ%" найдёт и «болт», и «Болт» — отдельно приводить регистр обычно не нужно.
Но настройка сравнения в итоге определяется параметрами базы данных на уровне СУБД. Если база создавалась с нестандартными параметрами сортировки, поведение может отличаться. Чтобы гарантировать регистронезависимость независимо от настроек, обе части приводят к одному регистру:
ГДЕ
ВРЕГ(Контрагенты.Наименование) ПОДОБНО ВРЕГ(&Шаблон)
У ВРЕГ() вокруг поля есть цена: обёртка функцией мешает использовать индекс. На больших таблицах это замедляет отбор, поэтому применяйте приём только когда регистронезависимость действительно под вопросом.
Буквы «е» и «ё» при стандартных настройках нередко считаются разными символами. Поиск «ёлка» может не найти записи «елка», введённые без «ё». Если данные заполнены неоднородно, надёжнее заменить «ё» на «е» и в поле, и в тексте поиска — либо, опять же, положиться на полнотекстовый поиск, который такие тонкости учитывает.
Почему «%текст%» тормозит и как ускорить отбор
Ключевой момент производительности — положение первого процента в шаблоне.
"текст%"— процент только в конце. СУБД может воспользоваться индексом по полю и найти нужные строки быстро, как поиск по началу слова в словаре."%текст%"и"%текст"— процент в начале. Индекс бесполезен: приходится прочитать и проверить каждую запись таблицы (полное сканирование).
На справочнике из 200 позиций разницы не видно. На таблице документов за несколько лет отбор по "%фрагмент%" может выполняться секунды. Что с этим делать:
- Если бизнес-логика позволяет искать по началу значения — используйте шаблон
"текст%"без ведущего процента. - Сузьте выборку другими условиями до
ПОДОБНО: отбор по периоду, организации, виду документа. Тогда полное сканирование пройдёт по сотням строк, а не по миллионам. - Для частого поиска по вхождению в большой объём текста переходите на полнотекстовый поиск с индексом.
- Не накладывайте
ПОДОБНОна вычисляемое выражение или на поле подВРЕГ(), если без этого можно обойтись — любая обёртка над полем отключает индекс.
Поиск «по мере ввода» в пользовательских формах почти всегда делают шаблоном "текст%" (по началу) — он и быстрый, и привычный для пользователя.
Готовые примеры под частые задачи
Найти документы, в номере которых встречается заданный фрагмент:
ВЫБРАТЬ
РеализацияТоваровУслуг.Ссылка,
РеализацияТоваровУслуг.Номер,
РеализацияТоваровУслуг.Дата
ИЗ
Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ГДЕ
РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода
И РеализацияТоваровУслуг.Номер ПОДОБНО &Шаблон СПЕЦСИМВОЛ "~"
Отбор по периоду стоит до ПОДОБНО — он сокращает набор строк, которые придётся сканировать.
Найти контрагентов, у которых заполнен хотя бы один из двух реквизитов фрагментом текста:
ГДЕ
Контрагенты.Наименование ПОДОБНО &Шаблон
ИЛИ Контрагенты.ПолноеНаименование ПОДОБНО &Шаблон
Отобрать коды строго из четырёх символов, которые начинаются на цифру:
ГДЕ
Номенклатура.Артикул ПОДОБНО "[0-9]___"
Шаблон "[0-9]___" — одна цифра плюс три любых символа, ровно четыре позиции. Если нужно «не меньше четырёх», добавьте % в конец: "[0-9]___%".
Найти документы, в табличной части которых есть товар с нужным фрагментом в наименовании. Здесь поиск идёт по полю, полученному через точку от строки табличной части:
ВЫБРАТЬ РАЗЛИЧНЫЕ
ПоступлениеТовары.Ссылка
ИЗ
Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТовары
ГДЕ
ПоступлениеТовары.Номенклатура.Наименование ПОДОБНО "%кабель%"
Ключевое слово РАЗЛИЧНЫЕ убирает дубли: если подходящих строк в одном документе несколько, ссылка на документ вернётся один раз.
Проверить себя на спецсимволах:
Частые ошибки при поиске подстроки
ПОДОБНО "текст" ищет точное равенство. Для вхождения нужно ПОДОБНО "%текст%".% и _ в искомом тексте не экранированы. Объявите СПЕЦСИМВОЛ и экранируйте ввод перед подстановкой в шаблон.&Шаблон равен просто «кабель», найдётся только строка, равная «кабель». Проценты добавляйте в коде: "%" + Текст + "%".%, индекс не используется. Сузьте выборку другими условиями или ищите по началу значения шаблоном "текст%".[. Его тоже нужно экранировать в функции подготовки шаблона.Частые вопросы
Можно ли использовать ПОДОБНО в системе компоновки данных (СКД)?
ПОДОБНО доступен и в тексте запроса набора данных, и в отборах. Для отбора по вхождению в настройках компоновки выбирают вид сравнения «Содержит» — он внутри превращается в ПОДОБНО с процентами.Чем ПОДОБНО отличается от полнотекстового поиска?
ПОДОБНО ищет точную подстроку в конкретном реквизите и на больших данных сканирует таблицу целиком. Полнотекстовый поиск работает по индексу сразу по многим реквизитам, понимает словоформы и быстрее на объёмах, но требует включения и регламентного обновления индекса.Как найти записи, где поле НЕ содержит подстроку?
НЕ перед условием: НЕ Поле ПОДОБНО "%текст%". Учтите, что строки с пустым (NULL) значением такое условие может не вернуть — при необходимости добавьте проверку на пустое значение.Нужно ли приводить регистр через ВРЕГ?
ВРЕГ не нужен. Он оправдан, только если настройки сравнения в базе нестандартные. Помните, что ВРЕГ вокруг поля отключает индекс.