Как найти элементы справочника, наименование которых заканчивается на определенные символы в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Решение задачи с помощью оператора ПОДОБНО в запросах

Для фильтрации данных по текстовому шаблону на уровне СУБД в языке запросов 1С применяется оператор ПОДОБНО (аналог оператора LIKE в стандартном SQL). Этот оператор позволяет сравнивать строковое поле со специальным шаблоном, в котором можно использовать служебные спецсимволы.

Разберем основные спецсимволы, которые поддерживает оператор ПОДОБНО:

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

Проанализируем пример готового запроса для решения нашей задачи:


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

В данном случае СУБД проанализирует поле Наименование и выберет только те элементы, которые заканчиваются на символы (Брак). Перед этой строкой может идти абсолютно любая последовательность символов произвольной длины.

Регистронезависимость поиска: особенности СУБД и встроенного языка

В процессе обсуждения подобных задач часто возникает вопрос: нужно ли программно обрабатывать регистр букв? Например, искать отдельно "(Брак)", "(брак)" или "(БРАК)" с помощью оператора ИЛИ? Разберем этот нюанс подробнее.

Здесь важно разделять поведение системы при выполнении запроса в СУБД и при обработке строк во встроенном языке в оперативной памяти:

  1. Поведение в запросах (на уровне СУБД): В связке с платформой «1С:Предприятие» базы данных (MS SQL Server, PostgreSQL, IBM DB2) по умолчанию создаются с регистронезависимым сопоставлением (для MS SQL Server это обычно параметры семейства Cyrillic_General_CI_AS, где CI означает Case Insensitive — регистронезависимый). Благодаря этому оператор ПОДОБНО "%(Брак)" автоматически найдет элементы с окончаниями "(брак)", "(БРАК)" и даже "(БрАк)". Дополнительные конструкции с ИЛИ или шаблоны вида "%([Бб][Рр][Аа][Кк])" в запросах являются избыточными и лишь усложняют чтение кода и замедляют выполнение запроса.
  2. Поведение во встроенном языке (в оперативной памяти): В отличие от запросов, встроенный язык 1С чувствителен к регистру при прямом сравнении строк. Если вы получаете выборку и в цикле сравниваете значения, используя конструкцию Если Текст = "значение" Тогда, система вернет ложь при несовпадении регистра букв. При работе с кодом в памяти обязательно приводите строки к одному регистру с помощью встроенных функций ВРег() или НРег():

// Пример проверки во встроенном языке 1С
Если Прав(НРег(СокрЛП(ВыборкаДетальныеЗаписи.Наименование)), 6) = "(брак)" Тогда
    // Действие при совпадении условий
КонецЕсли;

Проблема производительности: использование "%" в начале шаблона

Несмотря на то что запрос с шаблоном ПОДОБНО "%(Брак)" полностью решает функциональную задачу, у него есть серьезный скрытый недостаток, связанный с падением производительности информационной базы.

Рассмотрим по шагам, как СУБД выполняет данный запрос:

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

  1. Предварительное ограничение выборки: Никогда не выполняйте полнотабличный поиск без дополнительных условий. Постарайтесь ограничить выборку конкретными индексированными полями. Например, ищите только в определенных группах номенклатуры (по полю Родитель), отбирайте только не помеченные на удаление элементы или делайте отбор по конкретному виду номенклатуры.
  2. Использование полнотекстового поиска (ППД): Если задача поиска по части строки в справочнике возникает постоянно и выполняется интерактивно пользователями, целесообразно использовать встроенные механизмы полнотекстового поиска платформы «1С:Предприятие», которые работают на основе предрассчитанных индексов и не нагружают СУБД сложными сканирующими запросами.

Ограничения СУБД при использовании сложных шаблонов в 1С

В процессе оптимизации запросов или попыток обойти чувствительность к регистру разработчики иногда используют конструкции с квадратными скобками (например, ПОДОБНО "%[Бб][Рр][Аа][Кк]"). При написании таких запросов необходимо учитывать требования стандарта разработки 1С #std726, накладывающего ограничения на использование подобных конструкций на различных СУБД:

Современная альтернатива: Использование регулярных выражений

Начиная с версии платформы 1С:Предприятие 8.3.23, разработчикам стал доступен штатный кроссплатформенный механизм работы с регулярными выражениями (Regex) непосредственно во встроенном языке. До этого для работы с регулярными выражениями приходилось использовать COM-объекты операционной системы Windows (например, VBScript.RegExp), что делало код несовместимым с серверами под управлением Linux.

Хотя регулярные выражения нельзя использовать непосредственно внутри текста запроса на уровне СУБД, они идеально подходят для постобработки полученных результатов, валидации вводимых пользователем данных при записи или разбора сложных текстовых файлов. Для этого используются новые встроенные функции, такие как СтрНайтиПоРегулярномуВыражению(), СтрЗаменитьПоРегулярномуВыражению(), а также логическая функция проверки соответствия СтрПодобно().

Рассмотрим пример использования регулярных выражений во встроенном языке для нашей задачи:


// Шаблон регулярного выражения: 
// (?i) - включает регистронезависимый поиск
// \(брак\) - экранированные круглые скобки и слово "брак"
// $ - якорь конца строки, гарантирует поиск именно в конце наименования
ШаблонРегулярки = "(?i)\(брак\)$";

Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
    Если СтрПодобно(Выборка.Наименование, ШаблонРегулярки) Тогда
        // Найдено точное совпадение в конце наименования независимо от регистра букв
        Сообщить("Элемент с браком: " + Выборка.Наименование);
    КонецЕсли;
КонецЦикла;

Этот способ обеспечивает максимальную гибкость и точность разбора текстовой информации без необходимости написания сложных алгоритмов ручного посимвольного анализа строк во встроенном языке 1С.

← На главную