Как в запросе 1С проверить соответствие строки шаблону с переменным количеством цифр?

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

При разработке и доработке конфигураций 1С разработчики нередко сталкиваются с задачей валидации и фильтрации строковых данных непосредственно на уровне языка запросов. Типичный сценарий — проверка соответствия строки определенному формату, например, когда строка должна представлять собой конструкцию вида NNN/NNN/, где N — это цифра, а количество цифр в каждом блоке может варьироваться от 1 до 3 (например, 1/1/, 22/150/, 999/5/).

Разберем детально, какие возможности предоставляет язык запросов платформы 1С:Предприятие, почему стандартный оператор ПОДОБНО имеет ограничения, и какие есть эффективные способы решения этой задачи как на уровне запроса, так и на уровне архитектуры прикладного решения.

Ограничения оператора ПОДОБНО в языке запросов 1С

Проанализируем работу строкового оператора ПОДОБНО. В языке запросов 1С этот оператор транслируется в конструкцию LIKE соответствующей СУБД (Microsoft SQL Server, PostgreSQL, Oracle и др.). Набор специальных символов для сопоставления шаблонов в 1С строго ограничен:

  1. % — любая последовательность произвольных символов произвольной длины (включая нулевую длину).
  2. _ — ровно один произвольный символ.
  3. [...] — ровно один одиночный символ из указанного диапазона или перечисления (например, [0-9]).
  4. [^...] — ровно один одиночный символ, кроме входящих в указанный диапазон или перечисление.
  5. СПЕЦСИМВОЛ — символ экранирования управляющих знаков.

В отличие от механизмов регулярных выражений (RegEx), в языке запросов 1С отсутствуют квантификаторы повторений (такие как +, * или диапазон {1,3}). По этой причине задать конструкцию «от одной до трех цифр» одним простым символом в шаблоне невозможно.

Способ 1. Прямой перебор комбинаций через ПОДОБНО и ИЛИ

Рассмотрим прямолинейное решение, к которому чаще всего прибегают разработчики. Если длина числового блока строго ограничена от 1 до 3 символов, то каждый блок может состоять из одной, двух или трех цифр. Это дает 3 варианта для первого блока и 3 варианта для второго, то есть суммарно 9 возможных комбинаций.

Посмотрим на пример формирования условия в секции ГДЕ:


ВЫБРАТЬ
    Таблица.Ссылка КАК Ссылка,
    Таблица.СтроковоеПоле КАК СтроковоеПоле
ИЗ
    Справочник.Номенклатура КАК Таблица
ГДЕ
    Таблица.СтроковоеПоле ПОДОБНО "[0-9]/[0-9]/"
    ИЛИ Таблица.СтроковоеПоле ПОДОБНО "[0-9]/[0-9][0-9]/"
    ИЛИ Таблица.СтроковоеПоле ПОДОБНО "[0-9]/[0-9][0-9][0-9]/"
    ИЛИ Таблица.СтроковоеПоле ПОДОБНО "[0-9][0-9]/[0-9]/"
    ИЛИ Таблица.СтроковоеПоле ПОДОБНО "[0-9][0-9]/[0-9][0-9]/"
    ИЛИ Таблица.СтроковоеПоле ПОДОБНО "[0-9][0-9]/[0-9][0-9][0-9]/"
    ИЛИ Таблица.СтроковоеПоле ПОДОБНО "[0-9][0-9][0-9]/[0-9]/"
    ИЛИ Таблица.СтроковоеПоле ПОДОБНО "[0-9][0-9][0-9]/[0-9][0-9]/"
    ИЛИ Таблица.СтроковоеПоле ПОДОБНО "[0-9][0-9][0-9]/[0-9][0-9][0-9]/"

Особенности способа:

  1. Код является рабочим и гарантирует точный отбор строк.
  2. Конструкция становится громоздкой при увеличении допустимого диапазона (например, если бы цифр могло быть от 1 до 10, количество условий ИЛИ выросло бы до 100).

Способ 2. Метод исключений (инверсия условий через логическое И)

Разберем более изящный алгоритмический прием, который позволяет описать шаблон любой длины через фиксацию структуры и наложение запретов. Вместо перечисления всех разрешенных комбинаций мы формулируем правила, которым обязана соответствовать строка, соединенные оператором И.

Сформулируем правила валидности строки:

  1. Строка имеет базовую структуру со слэшами и заканчивается на слэш: ПОДОБНО "%/%/".
  2. Строка не начинается со слэша (первый блок не пустой): НЕ ПОДОБНО "/%".
  3. В строке нет третьего слэша (ровно два разделителя): НЕ ПОДОБНО "%/%/%/".
  4. В строке нет пустых блоков (два слэша подряд): НЕ ПОДОБНО "%//%".
  5. В строке отсутствуют любые посторонние символы, кроме цифр и слэша: НЕ ПОДОБНО "%[^0-9/]%".
  6. В строке нет числовых блоков длиннее 3 цифр подряд: НЕ ПОДОБНО "%[0-9][0-9][0-9][0-9]%".

Посмотрим на пример реализации в запросе:


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

Такой подход читается компактнее и легко модифицируется: если максимальное количество цифр увеличится до 5, достаточно изменить лишь последнее отрицание на проверку 6 цифр подряд.

Способ 3. Проверка на встроенном языке с помощью регулярных выражений (платформа 8.3.23+)

Проанализируем ситуацию, когда проверку можно перенести на уровень встроенного языка — например, при постобработке выборки запроса или перед записью объекта. Начиная с версии платформы 8.3.23, в 1С появились встроенные нативные методы для работы с регулярными выражениями.

Рассмотрим функцию СтрСоответствуетПоРегулярномуВыражению(). Она позволяет проверить строку по регулярному выражению ^\d{1,3}/\d{1,3}/$ буквально в одну строку кода.


// Пример проверки строки на соответствие шаблону
ШаблонРегЭксп = "^\d{1,3}/\d{1,3}/$";

Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
    Если СтрСоответствуетПоРегулярномуВыражению(Выборка.СтроковоеПоле, ШаблонРегЭксп) Тогда
        // Строка полностью соответствует формату [1-3 цифры]/[1-3 цифры]/
        ОбработатьКорректнуюСтроку(Выборка.Ссылка);
    КонецЕсли;
КонецЦикла;

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

  1. Высокая производительность выполнения на стороне сервера 1С.
  2. Кроссплатформенность: функции работают на Windows, Linux, macOS и мобильной платформе без сторонних библиотек.
  3. Читаемость и гибкость настройки шаблонов любой сложности.

Способ 4. Архитектурная оптимизация и влияние на производительность СУБД

Выясним причину замечаний о падении производительности при использовании сложных условий ПОДОБНО в запросах. Когда запрос содержит условия вида ПОДОБНО "%..." (с маской в начале) или отрицания НЕ ПОДОБНО, оптимизатор СУБД не может применить индексный поиск (Index Seek) по строковому полю. Это приводит к полному сканированию таблицы или индекса (Table Scan / Index Scan).

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

Рассмотрим правильные архитектурные альтернативы:

  1. Нормализация структуры данных. Вместо хранения составной строки создадим два отдельных числовых реквизита: ЧисловаяЧасть1 и ЧисловаяЧасть2. В этом случае проверка в запросе сводится к быстрому индексному условию:
    
    ГДЕ
        Таблица.ЧисловаяЧасть1 МЕЖДУ 0 И 999
        И Таблица.ЧисловаяЧасть2 МЕЖДУ 0 И 999
    
  2. Использование флага соответствия. Добавим в объект реквизит СоответствуетШаблону с типом Булево и включенным индексированием. В модуле объекта в процедуре ПередЗаписью вычисляем значение этого флага с помощью регулярного выражения. Тогда запрос будет максимально быстрым:
    
    ГДЕ
        Таблица.СоответствуетШаблону = ИСТИНА
    

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

← На главную