Условие «содержит» в языке запросов: шаблоны ПОДОБНО

· 9 мин

Содержание

Условие «содержит» в языке запросов 1С задаётся оператором ПОДОБНО и шаблоном с процентами по краям: Поле ПОДОБНО "%текст%". Проценты слева и справа означают «любой набор символов — искомый фрагмент — любой набор символов», то есть поле содержит эту подстроку в любом месте.

Отдельной функции «Содержит» в языке запросов нет. Во встроенном языке есть СтрНайти, но в запросе её вызвать нельзя — отбор по вхождению подстроки делают именно через ПОДОБНО. Это работает для реквизитов типа «Строка»: наименований, комментариев, артикулов, номеров документов.

Один нюанс стоит держать в голове сразу: шаблон с процентом в начале ("%текст%" или "%текст") заставляет СУБД читать таблицу целиком. На справочнике в сотню элементов это незаметно, на документах за несколько лет — уже тормозит. Как этого избежать, разберём ниже.

Как устроен шаблон: проценты, подчёркивание и наборы

ПОДОБНО сравнивает значение поля с шаблоном. В шаблоне обычные символы означают сами себя, а несколько символов — специальные:

  • % — любое количество любых символов, в том числе ноль символов;
  • _ (подчёркивание) — ровно один любой символ;
  • [абв] — один символ из перечисленного набора;
  • [а-я] — один символ из диапазона;
  • [^абв] — один символ, которого нет в наборе.

Отсюда три базовых сценария:

Что нужноШаблонЧто найдёт
Содержит фрагмент"%болт%"«Болт М6», «Комплект болтов»
Начинается с фрагмента"болт%"«Болт М6», но не «Комплект болтов»
Заканчивается фрагментом"%оцинк"«Болт оцинк»

Простейший запрос на вхождение подстроки:

ВЫБРАТЬ
    Номенклатура.Ссылка,
    Номенклатура.Наименование
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.Наименование ПОДОБНО "%кабель%"

Запрос вернёт все элементы, в наименовании которых встречается «кабель» — и «Кабель ВВГ», и «Гофра для кабеля».

Подчёркивание удобно, когда известна структура строки. Шаблон "__-___" найдёт коды вида «АБ-123»: две буквы, дефис, три символа.

Как искать знак процента и подчёркивание в самом тексте

Проблема возникает, когда искомый фрагмент сам содержит % или _. Например, нужно найти номенклатуру со скидкой «30%». Шаблон "%30%%" сработает неправильно: второй % платформа примет за спецсимвол «любые символы», а не за знак процента.

Решение — объявить символ экранирования через ключевое слово СПЕЦСИМВОЛ. Символ, стоящий после него в шаблоне, теряет специальное значение:

ВЫБРАТЬ
    Товары.Наименование
ИЗ
    Справочник.Номенклатура КАК Товары
ГДЕ
    Товары.Наименование ПОДОБНО "%30!%%" СПЕЦСИМВОЛ "!"

Разбор шаблона "%30!%%" при СПЕЦСИМВОЛ "!": % (любой текст) + 30 + !% (буквальный знак процента) + % (любой текст). Запрос найдёт любую строку, где встречается «30%».

В роли экранирующего можно взять любой символ, которого заведомо нет в данных — чаще всего это !, ~ или \. Чтобы найти буквальное подчёркивание, пишут "%!_%" с тем же СПЕЦСИМВОЛ "!".

Без СПЕЦСИМВОЛ экранировать нельзя — платформа просто не поймёт, что символ должен быть буквальным.

Как собрать шаблон в параметре из пользовательского ввода

В реальной задаче текст поиска вводит пользователь, а не прописан в запросе. Тогда в тексте запроса ставят параметр:

ВЫБРАТЬ
    Контрагенты.Ссылка,
    Контрагенты.Наименование
ИЗ
    Справочник.Контрагенты КАК Контрагенты
ГДЕ
    Контрагенты.Наименование ПОДОБНО &Шаблон СПЕЦСИМВОЛ "~"

А проценты добавляют уже в коде, при установке параметра:

Запрос.УстановитьПараметр("Шаблон", "%" + ЭкранироватьСпецсимволы(ТекстПоиска) + "%");

Пользовательский ввод обязательно экранируйте. Иначе, если человек введёт «50%», поиск поведёт себя непредсказуемо, а символ [ и вовсе может вызвать ошибку шаблона. Готовая функция экранирования:

Функция ЭкранироватьСпецсимволы(Текст)
    // сначала экранируем сам символ экранирования
    Результат = СтрЗаменить(Текст, "~", "~~");
    Результат = СтрЗаменить(Результат, "%", "~%");
    Результат = СтрЗаменить(Результат, "_", "~_");
    Результат = СтрЗаменить(Результат, "[", "~[");
    Возврат Результат;
КонецФункции

Порядок важен: экранирующий символ (~) обрабатываем первым, иначе вставленные позже ~% и ~_ экранируются повторно и ломаются.

Чем ПОДОБНО отличается от ПОДСТРОКА и других функций

В языке запросов есть строковые функции, но ищет вхождение только ПОДОБНО. Остальные решают смежные задачи:

  • ПОДСТРОКА(Строка, Начало, Длина) — вырезает кусок строки по позиции. Это не поиск: позицию нужно знать заранее.
  • ВРЕГ(Строка) и НРЕГ(Строка) — приводят строку к верхнему или нижнему регистру.
  • СОКРЛП(Строка) — убирает пробелы по краям.

Частая ошибка — попытаться вызвать в запросе СтрНайти или СтрДлина. Эти функции доступны только во встроенном языке, в тексте запроса их нет, и запрос с ними просто не выполнится.

Если фрагментов несколько и важно их взаимное расположение, их комбинируют. Например, «начинается на „АКТ“ и где-то дальше содержит „2024“»:

ГДЕ
    Документ.Номер ПОДОБНО "АКТ%"
    И Документ.Номер ПОДОБНО "%2024%"

Для поиска по большим текстовым полям (назначение платежа, длинные комментарии, содержимое присоединённых файлов) есть отдельный механизм — полнотекстовый поиск. Он работает по индексу, понимает словоформы и на объёмных данных в разы быстрее, чем ПОДОБНО "%…%". Включается в разделе Администрирование, а в коде используется объект ПолнотекстовыйПоиск. Для точного поиска подстроки в конкретном реквизите ПОДОБНО остаётся основным инструментом, для «найти упоминание» по всей базе — полнотекстовый поиск уместнее.

Когда для отбора лучше взять другое условие

ПОДОБНО — инструмент именно для поиска по фрагменту текста. Если задача другая, он только замедлит запрос и даст лишние совпадения.

  • Точное значение известно. Ищете конкретный элемент справочника или перечисления — сравнивайте по ссылке через =: Товар.Вид = &ВидТовара. Это быстро и однозначно.
  • Отбор по началу кода или номера. Если коды строго структурированы (например, все договоры филиала начинаются на «Ф-»), подойдёт шаблон по началу "Ф-%" — но без ведущего процента, чтобы работал индекс.
  • Сравнение чисел и дат. ПОДОБНО работает только со строками. Для дат и сумм используйте МЕЖДУ, >=, <= — приводить их к строке и искать подстроку нельзя и не нужно.
  • Проверка на заполненность. Чтобы найти записи с непустым реквизитом, берите Поле <> "" или Поле <> NULL, а не ПОДОБНО "%".

Хорошее правило: если во фрагменте нет неопределённости по позиции («где-то внутри строки»), то ПОДОБНО, скорее всего, лишний.

Регистр и буква «ё»: на что обратить внимание

В типовой поставке сравнение строк в запросе регистронезависимое. "%БОЛТ%" найдёт и «болт», и «Болт» — отдельно приводить регистр обычно не нужно.

Но настройка сравнения в итоге определяется параметрами базы данных на уровне СУБД. Если база создавалась с нестандартными параметрами сортировки, поведение может отличаться. Чтобы гарантировать регистронезависимость независимо от настроек, обе части приводят к одному регистру:

ГДЕ
    ВРЕГ(Контрагенты.Наименование) ПОДОБНО ВРЕГ(&Шаблон)

У ВРЕГ() вокруг поля есть цена: обёртка функцией мешает использовать индекс. На больших таблицах это замедляет отбор, поэтому применяйте приём только когда регистронезависимость действительно под вопросом.

Буквы «е» и «ё» при стандартных настройках нередко считаются разными символами. Поиск «ёлка» может не найти записи «елка», введённые без «ё». Если данные заполнены неоднородно, надёжнее заменить «ё» на «е» и в поле, и в тексте поиска — либо, опять же, положиться на полнотекстовый поиск, который такие тонкости учитывает.

Почему «%текст%» тормозит и как ускорить отбор

Ключевой момент производительности — положение первого процента в шаблоне.

  • "текст%" — процент только в конце. СУБД может воспользоваться индексом по полю и найти нужные строки быстро, как поиск по началу слова в словаре.
  • "%текст%" и "%текст" — процент в начале. Индекс бесполезен: приходится прочитать и проверить каждую запись таблицы (полное сканирование).

На справочнике из 200 позиций разницы не видно. На таблице документов за несколько лет отбор по "%фрагмент%" может выполняться секунды. Что с этим делать:

  1. Если бизнес-логика позволяет искать по началу значения — используйте шаблон "текст%" без ведущего процента.
  2. Сузьте выборку другими условиями до ПОДОБНО: отбор по периоду, организации, виду документа. Тогда полное сканирование пройдёт по сотням строк, а не по миллионам.
  3. Для частого поиска по вхождению в большой объём текста переходите на полнотекстовый поиск с индексом.
  4. Не накладывайте ПОДОБНО на вычисляемое выражение или на поле под ВРЕГ(), если без этого можно обойтись — любая обёртка над полем отключает индекс.

Поиск «по мере ввода» в пользовательских формах почти всегда делают шаблоном "текст%" (по началу) — он и быстрый, и привычный для пользователя.

Готовые примеры под частые задачи

Найти документы, в номере которых встречается заданный фрагмент:

ВЫБРАТЬ
    РеализацияТоваровУслуг.Ссылка,
    РеализацияТоваровУслуг.Номер,
    РеализацияТоваровУслуг.Дата
ИЗ
    Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ГДЕ
    РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода
    И РеализацияТоваровУслуг.Номер ПОДОБНО &Шаблон СПЕЦСИМВОЛ "~"

Отбор по периоду стоит до ПОДОБНО — он сокращает набор строк, которые придётся сканировать.

Найти контрагентов, у которых заполнен хотя бы один из двух реквизитов фрагментом текста:

ГДЕ
    Контрагенты.Наименование ПОДОБНО &Шаблон
    ИЛИ Контрагенты.ПолноеНаименование ПОДОБНО &Шаблон

Отобрать коды строго из четырёх символов, которые начинаются на цифру:

ГДЕ
    Номенклатура.Артикул ПОДОБНО "[0-9]___"

Шаблон "[0-9]___" — одна цифра плюс три любых символа, ровно четыре позиции. Если нужно «не меньше четырёх», добавьте % в конец: "[0-9]___%".

Найти документы, в табличной части которых есть товар с нужным фрагментом в наименовании. Здесь поиск идёт по полю, полученному через точку от строки табличной части:

ВЫБРАТЬ РАЗЛИЧНЫЕ
    ПоступлениеТовары.Ссылка
ИЗ
    Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТовары
ГДЕ
    ПоступлениеТовары.Номенклатура.Наименование ПОДОБНО "%кабель%"

Ключевое слово РАЗЛИЧНЫЕ убирает дубли: если подходящих строк в одном документе несколько, ссылка на документ вернётся один раз.

Проверить себя на спецсимволах:

Проверьте себя
Какой шаблон найдёт строки, которые заканчиваются на «кг»?
Что означает `_` (подчёркивание) в шаблоне ПОДОБНО?
Как в шаблоне искать буквальный знак процента?

Частые ошибки при поиске подстроки

Диагностика: выберите симптом

Частые вопросы

Можно ли использовать ПОДОБНО в системе компоновки данных (СКД)?
Да. В СКД ПОДОБНО доступен и в тексте запроса набора данных, и в отборах. Для отбора по вхождению в настройках компоновки выбирают вид сравнения «Содержит» — он внутри превращается в ПОДОБНО с процентами.
Чем ПОДОБНО отличается от полнотекстового поиска?
ПОДОБНО ищет точную подстроку в конкретном реквизите и на больших данных сканирует таблицу целиком. Полнотекстовый поиск работает по индексу сразу по многим реквизитам, понимает словоформы и быстрее на объёмах, но требует включения и регламентного обновления индекса.
Как найти записи, где поле НЕ содержит подстроку?
Добавьте частицу НЕ перед условием: НЕ Поле ПОДОБНО "%текст%". Учтите, что строки с пустым (NULL) значением такое условие может не вернуть — при необходимости добавьте проверку на пустое значение.
Нужно ли приводить регистр через ВРЕГ?
В большинстве баз сравнение и так регистронезависимое, и ВРЕГ не нужен. Он оправдан, только если настройки сравнения в базе нестандартные. Помните, что ВРЕГ вокруг поля отключает индекс.
Почему поиск по русскому тексту с «ё» ничего не находит?
При стандартных параметрах базы «е» и «ё» часто считаются разными буквами. Либо приведите обе буквы к «е» в поле и в шаблоне, либо используйте полнотекстовый поиск.