Почему не работает условие ПОДОБНО в запросе 1С при передаче параметра с процентом?

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

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

Выясняем причину: невидимые пробелы и спецсимволы

Рассмотрим распространенный сценарий. Запрос написан следующим образом:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |	ЗаказПокупателя.Ссылка КАК ЗаказПокупателя
    |ИЗ
    |	Документ.ЗаказПокупателя КАК ЗаказПокупателя
    |ГДЕ
    |	ЗаказПокупателя.Номер ПОДОБНО &Номер
    |	И ЗаказПокупателя.Дата МЕЖДУ &ДатаС И &ДатаПо
    |УПОРЯДОЧИТЬ ПО
    |	ЗаказПокупателя.Дата УБЫВ";

Запрос.УстановитьПараметр("Номер", "%" + Номер);
Запрос.УстановитьПараметр("ДатаС", ДатаС);
Запрос.УстановитьПараметр("ДатаПо", ДатаПо);

В отладчике значение переменной Номер может выглядеть как обычные цифры "4107". Однако при подстановке в параметр запрос не находит ни одного документа. При этом явная передача строки "%4107" работает корректно.

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

Способ 1. Очистка строки с помощью функции СокрЛП

Разберем самое простое и эффективное решение этой проблемы. Перед конкатенацией строки с символом процента необходимо применить функцию СокрЛП, которая удаляет концевые и начальные пробелы.

Исправленный код обработки параметра выглядит следующим образом:


// Очищаем номер от концевых и начальных пробелов
ЧистыйНомер = СокрЛП(Номер);

// Устанавливаем параметр шаблона для поиска
Запрос.УстановитьПараметр("Номер", "%" + ЧистыйНомер);
Запрос.УстановитьПараметр("ДатаС", ДатаС);
Запрос.УстановитьПараметр("ДатаПо", ДатаПо);

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

Использование СокрЛП отсекает все лишние пробелы, благодаря чему сформированный шаблон принимает корректный вид "%4107" и запрос находит нужный документ.

Способ 2. Глубокая очистка от неразрывных пробелов и управляющих символов

Иногда обычного применения СокрЛП оказывается недостаточно. При загрузке данных из сторонних систем строка может содержать неразрывные пробелы (Символы.НПП) или символы табуляции (Символы.Таб), которые стандартная функция обрезки пробелов не удаляет.

Посмотрим, как выполнить полную очистку строки перед передачей в параметр запроса:


// Удаляем неразрывные пробелы и табуляцию
ЧистыйНомер = СтрЗаменить(Номер, Символы.НПП, "");
ЧистыйНомер = СтрЗаменить(ЧистыйНомер, Символы.Таб, "");

// Удаляем обычные начальные и концевые пробелы
ЧистыйНомер = СокрЛП(ЧистыйНомер);

Запрос.УстановитьПараметр("Номер", "%" + ЧистыйНомер);

Особенности работы оператора ПОДОБНО и экранирование спецсимволов

При работе с условием ПОДОБНО в языке запросов 1С полезно учитывать несколько важных правил:

  1. Подготовка шаблона в коде: Всю строку шаблона вместе с символами % и _ необходимо формировать в коде 1С и передавать через параметр &Номер, а не конкатенировать строки в самом тексте запроса.
  2. Экранирование спецсимволов: Если искомый номер или подстрока содержат символы % или _ как часть самого значения, их необходимо экранировать с помощью конструкции СПЕЦСИМВОЛ.
    
    // Подготавливаем спецсимволы
    ИскомыйТекст = СтрЗаменить(Номер, "%", "~%");
    ИскомыйТекст = СтрЗаменить(ИскомыйТекст, "_", "~_");
    
    Запрос.УстановитьПараметр("Номер", "%" + СокрЛП(ИскомыйТекст));
    
    // В тексте запроса указываем символ экранирования:
    // ГДЕ ЗаказПокупателя.Номер ПОДОБНО &Номер СПЕЦСИМВОЛ "~"
    
  3. Влияние на производительность: Поиск по шаблону, начинающемуся с процента (например, "%4107"), приводит к тому, что СУБД не может задействовать индексы по полю Номер. Если задача позволяет искать по началу строки (например, "4107%"), рекомендуется использовать такой шаблон для исключения полного сканирования таблицы.
← На главную