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

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

При разработке конфигураций на платформе 1С часто возникает задача поиска ссылок на справочники по параметрам, которые могут быть записаны в разном формате. Например, в базе данных номер может храниться как 1234 567 89, 98-76 456-09 или 64 37 903-940, а от пользователя приходит чистая строка 123456789. Возникает естественное желание использовать СтрЗаменить прямо в языке запросов, чтобы очистить данные от пробелов и спецсимволов. Однако, давайте разберемся, почему это невозможно и как правильно решить такую задачу.

Почему СтрЗаменить в запросе не работает?

Язык запросов 1С ориентирован на работу с индексированными данными SQL-серверов. Использование функций обработки строк типа СтрЗаменить непосредственно внутри запроса привело бы к тому, что для каждой записи таблицы базе данных пришлось бы выполнять программную модификацию строки. Это исключает возможность использования индексов, что неизбежно ведет к полному сканированию всей таблицы (Table Scan). При росте объема данных такой подход приведет к критическому падению производительности.

Архитектурно верные способы решения задачи

Вместо того чтобы пытаться «сломать» логику работы запросов, рассмотрим способы приведения данных к единому, «православному» формату на уровне архитектуры.

Вариант 1: Использование дополнительного реквизита

Это самый эффективный метод. Мы добавляем в справочник дополнительный реквизит (например, КодБезРазделителей), который будет хранить «чистое» значение номера. Заполнение этого реквизита можно автоматизировать с помощью подписки на событие ПриЗаписи.

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


Процедура ПриЗаписи(Отказ)
    // Очистка от любых символов, кроме цифр
    ЧистыйНомер = "";
    Для Сч = 1 По СтрДлина(ЭтотОбъект.Номер) Цикл
        Символ = Сред(ЭтотОбъект.Номер, Сч, 1);
        Если Найти("0123456789", Символ) > 0 Тогда
            ЧистыйНомер = ЧистыйНомер + Символ;
        КонецЕсли;
    КонецЦикла;
    ЭтотОбъект.КодБезРазделителей = ЧистыйНомер;
КонецПроцедуры

После того как вы прогоните разовую обработку по существующим элементам, поиск будет работать мгновенно, так как вы сможете наложить на реквизит КодБезРазделителей обычный индекс.

Вариант 2: Использование регистра сведений

Если внесение изменений в структуру справочника нежелательно (например, из-за сложности обновления конфигурации), используйте Регистр сведений. В нем можно хранить связь между ссылкой на элемент и его «очищенным» представлением.

  1. Создайте независимый регистр сведений, где измерением будет СсылкаНаСправочник, а ресурсом — ОчищенныйКод.
  2. При записи элемента в справочник обновляйте запись в регистре через ту же подписку.
  3. В запросе делайте ЛЕВОЕ СОЕДИНЕНИЕ с этим регистром.

Это позволит вам сохранить чистоту метаданных справочника, при этом обеспечив высокую скорость поиска через механизм соединений.

Почему «костыли» через ПОДСТРОКА — это плохая идея?

Иногда программисты пытаются использовать конструкцию ПОДСТРОКА и ПОДОБНО, проверяя каждый символ строки на соответствие цифре. Рассмотрим, как это выглядит в «лоб»:


ВЫБРАТЬ
    А.Ссылка
ИЗ
    Справочник.Клиенты КАК А
ГДЕ
    ВЫБОР КОГДА ПОДСТРОКА(А.Номер, 1, 1) ПОДОБНО "[0-9]" ТОГДА ... ИНАЧЕ "" КОНЕЦ + ...

Такой подход крайне не рекомендуется по нескольким причинам:

Итог

Профессиональный подход в разработке на 1С требует понимания принципов работы СУБД. Всегда старайтесь нормализовать данные на этапе их внесения в систему (Data Entry). Создание дополнительных реквизитов или регистров сведений — это стандартная практика, которая обеспечивает быстродействие и стабильность базы данных на долгие годы вперед. Не ищите способы «обмануть» запрос, а приводите данные к тому виду, в котором системе будет удобно с ними работать.

← На главную