При работе с данными в 1С часто возникает задача отфильтровать записи по наличию в текстовом поле определенных символов, например, специальных знаков: !, @, #, $, % и других. Стандартный оператор языка запросов ПОДОБНО (аналог LIKE в SQL) отлично подходит для поиска по шаблону, а качественная шпаргалка по языку запросов поможет быстрее сориентироваться в его синтаксисе. Однако использование этого оператора для набора символов имеет свои особенности. Рассмотрим, как правильно составить такое условие в запросе, и разберем распространенные ошибки.
Проанализируем ситуацию: разработчик пытается отобрать контрагентов, в наименовании которых есть хотя бы один спецсимвол. Интуитивная попытка написать условие выглядит так:
ГДЕ
Контрагент.Наименование ПОДОБНО "%!@#$%^&*()_+{}[]|:\";<>?/.,~`%"
Такой запрос не сработает и вызовет синтаксическую ошибку, потому что строка "!@#$%^&..." воспринимается как последовательность символов, а не как набор альтернатив "любой из этих символов". Давайте разберем правильные и эффективные способы решения этой задачи, которые обеспечат быстрый анализ данных в вашей информационной базе.
Самый простой и, что важно, универсальный способ — это перечислить условия для каждого искомого символа, объединив их логическим оператором ИЛИ. Этот подход будет работать на всех версиях платформы 1С:Предприятие и со всеми поддерживаемыми системами управления базами данных (СУБД).
Логика проста: мы проверяем, содержит ли строка первый спецсимвол, ИЛИ второй, ИЛИ третий, и так далее. Если хотя бы одно из условий истинно, запись попадет в выборку.
Посмотрим на пример:
Составим запрос, который найдет всех контрагентов, в наименовании которых есть символы "!", "@", "#" или "$".
ВЫБРАТЬ
Контрагенты.Ссылка,
Контрагенты.Наименование
ИЗ
Справочник.Контрагенты КАК Контрагенты
ГДЕ
(Контрагенты.Наименование ПОДОБНО "%!%"
ИЛИ Контрагенты.Наименование ПОДОБНО "%@%"
ИЛИ Контрагенты.Наименование ПОДОБНО "%#%"
ИЛИ Контрагенты.Наименование ПОДОБНО "%$%")
В этом примере символ % является метасимволом и означает любую последовательность символов (включая пустую). Конструкция "%!%" означает, что восклицательный знак может находиться в любом месте строки: в начале, в середине или в конце.
Преимущества этого метода:
Недостатки:
Язык запросов 1С поддерживает более изящный синтаксис для поиска любого символа из заданного набора. Для этого используются квадратные скобки [...]. Внутри скобок перечисляются все символы, которые мы хотим найти. Если вам требуется автоматизировать подобные фильтры в отчетах, можно использовать расширение для отборов на соответствие шаблону списком.
Давайте перепишем наш запрос с использованием этой конструкции:
ВЫБРАТЬ
Контрагенты.Ссылка,
Контрагенты.Наименование
ИЗ
Справочник.Контрагенты КАК Контрагенты
ГДЕ
Контрагенты.Наименование ПОДОБНО "%[!@#$%^&*()_+{}\[\]|:"";<>?/.,~`]%"
Разберем синтаксис подробнее:
% в начале и в конце шаблона, как и в прошлом примере, означают, что искомый символ может находиться где угодно в строке.[...] определяет набор символов. Запрос найдет строки, содержащие хотя бы один символ из этого набора.Важные нюансы и экранирование:
Некоторые символы внутри квадратных скобок могут иметь специальное значение. Важно знать, как их правильно использовать.
% и _: Внутри квадратных скобок они теряют свое специальное значение и воспринимаются как обычные символы. То есть, чтобы найти сам символ процента или подчеркивания, достаточно просто включить их в набор: "[%_]".^: Если этот символ стоит сразу после открывающей скобки ([^...]), он инвертирует условие. Запрос будет искать строки, содержащие любой символ, кроме перечисленных в скобках. Чтобы найти сам символ ^, его не следует ставить на первую позицию.]: Чтобы найти закрывающую квадратную скобку, ее нужно поместить сразу после открывающей: "[]...]".-: Дефис используется для указания диапазона символов (например, [а-я] или [0-9]). Чтобы найти сам дефис, его нужно поместить в начало или в конец набора: "[-...]" или "[...-]".Предупреждение о совместимости:
Несмотря на свою элегантность, этот метод имеет серьезный недостаток. Конструкция [...] не поддерживается в СУБД IBM DB2. Если ваше прикладное решение должно работать с этой СУБД, использование данного синтаксиса приведет к ошибкам. В таких случаях следует использовать первый, более надежный метод с оператором ИЛИ.
Иногда можно встретить предложение выбрать все данные из базы, а затем отфильтровать их в цикле уже средствами языка 1С.
// Этот подход НЕ РЕКОМЕНДУЕТСЯ для больших объемов данных!
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Контрагенты.Наименование
|ИЗ
| Справочник.Контрагенты КАК Контрагенты";
Результат = Запрос.Выполнить().Выгрузить();
НужныеСтроки = Новый Массив;
Для Каждого Строка Из Результат Цикл
// Здесь можно применить сложную проверку, например, с регулярными выражениями
Если НайденаСложнаяЗакономерность(Строка.Наименование) Тогда
НужныеСтроки.Добавить(Строка);
КонецЕсли;
КонецЦикла;
Почему этот метод плох для фильтрации?
Производительность. Выборка всех записей из таблицы (которая может содержать сотни тысяч или миллионы строк) создает огромную нагрузку на СУБД и сеть. Фильтрация данных всегда должна происходить на стороне СУБД, то есть внутри запроса, если это возможно. Этот метод оправдан только для очень сложных условий поиска, которые невозможно выразить языком запросов, и на заведомо небольших выборках.
Мы рассмотрели три способа поиска строк со спецсимволами. Подведем итог:
ПОДОБНО через оператор ИЛИ.[...].