Как реализовать поиск спецсимволов в Построителе запроса 1С?

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

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

Проблема использования конструкции СПЕЦСИМВОЛ в Построителе

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

Проблема заключается в том, что механизмы автоматической генерации запросов в объектах ПостроительЗапроса и даже в Системе компоновки данных (СКД) при использовании вида сравнения Содержит, Начинается с или Подобно жестко преобразуют значение в шаблон для SQL. При этом в интерфейсе программирования этих объектов отсутствует возможность указать символ экранирования. Платформа просто не добавляет ключевое слово СПЕЦСИМВОЛ в итоговый текст, а попытка «подклеить» его в саму строку значения приведет лишь к тому, что запрос будет искать это слово как часть текста.

Решение: Использование синтаксиса квадратных скобок

Разберем основной способ обхода этого ограничения. Вместо использования СПЕЦСИМВОЛ, мы можем воспользоваться встроенным функционалом языка запросов 1С — синтаксисом групп символов в квадратных скобках [...]. Это стандартная возможность регулярных выражений языка запросов, которая позволяет экранировать служебные знаки, заключая их в скобки.

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

Рассмотрим пример кода, демонстрирующий это решение для ПостроительЗапроса:


ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Стр", Новый ОписаниеТипов("Строка"));
ТЗ.Добавить().Стр = "ОбычныйТекст";
ТЗ.Добавить().Стр = "Текст_со_спецсимволом";

ПС = Новый ПостроительЗапроса;
ПС.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТЗ);

ЭлементОтбора = ПС.Отбор.Добавить("Стр");
ЭлементОтбора.Использование = Истина;
ЭлементОтбора.ВидСравнения = ВидСравнения.Содержит;

// Вместо использования "~_" мы заключаем подчеркивание в скобки
ЭлементОтбора.Значение = "[_]"; 

ПодходящиеСлова = ПС.Результат.Выгрузить();
Сообщить("Найдено строк: " + ПодходящиеСлова.Количество());

Правила экранирования различных символов

Выясним, как подготовить строку поиска для различных специальных знаков, если мы не можем задействовать СПЕЦСИМВОЛ:

  1. Символ подчеркивания (_): Превращается в [_]. В обычном состоянии он означает "любой один символ", но в скобках ищется именно как нижнее подчеркивание.
  2. Символ процента (%): Превращается в [%]. Перестает означать "любую последовательность символов".
  3. Открывающая квадратная скобка ([): Это самый интересный случай. Чтобы найти саму скобку, её нужно экранировать ею же: [[].
  4. Закрывающая квадратная скобка (]): В языке запросов 1С она не является специальным символом, если перед ней не была встречена открывающая скобка. Поэтому её можно указывать просто как ]. Однако для надежности в сложных шаблонах (например, при поиске пары []) рекомендуется шаблон [[]].
  5. Символ каретки (^): Внутри скобок в начале строки он означает инверсию. Чтобы найти его как символ, используйте [^].
  6. Тире (-): Означает диапазон (например, [0-9]). Чтобы найти тире как литерал, поместите его в начало или в конец списка внутри скобок: [-abc] или [abc-].

Особенности производительности и индексов

Проанализируем ситуацию с точки зрения эффективности базы данных. Важно понимать, что использование конструкций вида ПОДОБНО "%[_]%" (что фактически делает построитель при виде сравнения Содержит) накладывает серьезные ограничения на производительность:

Во-первых, любое условие, начинающееся с процента (или шаблона в скобках), делает невозможным использование индексов SQL-сервером по этому полю. Система будет вынуждена выполнить полное сканирование таблицы (Full Scan), что на больших объемах данных (миллионы строк) приведет к значительным задержкам.

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

Альтернативный подход: Изменение текста запроса

Если задача требует обязательного использования СПЕЦСИМВОЛ (например, для динамического формирования сложных условий), можно прибегнуть к следующему алгоритму:

  1. Отказаться от стандартного добавления отбора через ПС.Отбор.Добавить().
  2. В исходном тексте запроса построителя прописать условие в секции ГДЕ вручную, используя параметры.
  3. Использовать конструкцию {ГДЕ ...} для того, чтобы поле оставалось доступным в настройках, но логику сравнения описать самостоятельно.

Рассмотрим пример фрагмента запроса для построителя:


ВЫБРАТЬ
    СправочникНоменклатура.Ссылка,
    СправочникНоменклатура.Наименование
ИЗ
    Справочник.Номенклатура КАК СправочникНоменклатура
{ГДЕ
    (СправочникНоменклатура.Наименование ПОДОБНО &ШаблонПоиска СПЕЦСИМВОЛ "~")}

В этом случае вам придется самостоятельно программно подготовить переменную &ШаблонПоиска, добавив в неё нужные символы % и заэкранировав служебные знаки с помощью тильды или другого выбранного символа. Построитель корректно обработает такой текст запроса, сохранив возможность гибкой настройки остальных полей.

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

← На главную