Как правильно искать записи в регистре сведений через оператор ПОДОБНО в 1С?

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

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

Анализ проблемы: почему запрос не находит запись

Рассмотрим исходный фрагмент кода, в котором выполняется попытка найти человека по подстроке фамилии:


ФамилияИО = "Иванов";
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    Рег_ДР.ФамилияИО
    |ИЗ
    |    РегистрСведений.Рег_ДР КАК Рег_ДР
    |ГДЕ
    |    Рег_ДР.ФамилияИО ПОДОБНО &ФамилияИО
    |СГРУППИРОВАТЬ ПО
    |    Рег_ДР.ФамилияИО";

Запрос.УстановитьПараметр("ФамилияИО", ФамилияИО);
РезультатЗапроса = Запрос.Выполнить();

Выясним причину, почему такой запрос не находит строку "Иванов И.И." или "Иванов":

  1. Отсутствие спецсимволов маски: Оператор ПОДОБНО (аналог LIKE в SQL) без управляющих знаков % (любое количество символов) или _ (один произвольный символ) работает как точное строгое сравнение. Передав параметр "Иванов", мы ищем точное совпадение со всей строкой.
  2. Фиксированная длина строки: Если у измерения регистра сведений в метаданных задана строка фиксированной длины (например, Строка (20) с признаком фиксированной длины), СУБД автоматически дополняет значение пробелами справа до 20 символов ("Иванов "). При прямом сравнении строка из 6 символов "Иванов" никогда не будет равна строке из 20 символов с пробелами на конце.

Способ 1. Формирование шаблона поиска в коде (Рекомендуемый)

Наиболее надежный и чистый способ — подготовить строку с масками % во встроенном языке 1С перед передачей в параметр запроса. Посмотрим на пример реализации:


ФамилияИО = "Иванов";

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    Рег_ДР.ФамилияИО,
    |    Рег_ДР.ДатаДР
    |ИЗ
    |    РегистрСведений.Рег_ДР КАК Рег_ДР
    |ГДЕ
    |    Рег_ДР.ФамилияИО ПОДОБНО &ШаблонПоиска";

// Добавляем символы маски подстановки в параметр
Запрос.УстановитьПараметр("ШаблонПоиска", "%" + ФамилияИО + "%");

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    // Обработка найденных записей
КонецЦикла;

В данном случае условие "%" + ФамилияИО + "%" найдет любое вхождение подстроки "Иванов", независимо от того, какие символы или пробелы находятся слева или справа от искомого слова.

Способ 2. Конкатенация маски в тексте запроса

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    Рег_ДР.ФамилияИО
    |ИЗ
    |    РегистрСведений.Рег_ДР КАК Рег_ДР
    |ГДЕ
    |    Рег_ДР.ФамилияИО ПОДОБНО ""%"" + &ФамилияИО + ""%""";

Запрос.УстановитьПараметр("ФамилияИО", ФамилияИО);

Особенности строковых типов и удаление пробелов

Если в регистре используется строка фиксированной длины, а поиск требуется выполнить по точному началу или окончанию строки, пробелы СУБД могут исказить результат. В таком случае разберем использование функции СОКРЛП в запросе:


ГДЕ
    СОКРЛП(Рег_ДР.ФамилияИО) ПОДОБНО &ШаблонПоиска

Функция СОКРЛП удаляет незначащие пробелы в начале и конце строки перед выполнением проверки по шаблону.

Экранирование спецсимволов с помощью СПЕЦСИМВОЛ

Если пользовательский ввод может содержать зарезервированные символы (например, знак процента % или символ подчеркивания _), оператор ПОДОБНО воспримет их как маску. Чтобы искать их как обычный текст, используем конструкцию СПЕЦСИМВОЛ:


ГДЕ
    Рег_ДР.ФамилияИО ПОДОБНО &ШаблонПоиска СПЕЦСИМВОЛ "\"

В этом случае комбинация \% будет интерпретироваться как поиск буквального символа процента.

Рекомендации по производительности и архитектуре

  1. Индексация при поиске: Условие ПОДОБНО "%Иванов%" делает невозможным использование индексов СУБД (выполняется полное сканирование таблицы). Если логика позволяет искать только по началу строки ("Иванов%"), СУБД задействует индекс по измерению, что существенно ускорит выполнение запроса на больших объемах данных.
  2. Лишние группировки: Если ФамилияИО является единственным измерением регистра сведений, все записи по нему уже уникальны. Конструкции СГРУППИРОВАТЬ ПО или ВЫБРАТЬ РАЗЛИЧНЫЕ в таком запросе избыточны и создают дополнительную нагрузку на сервер баз данных.
  3. Выбор типов метаданных: Для хранения персональных данных и физических лиц рекомендуется использовать измерение ссылочного типа (например, СправочникСсылка.ФизическиеЛица), а не примитивный тип Строка. Это исключает дублирование записей из-за опечаток и обеспечивает целостность структуры базы данных.
← На главную