Как правильно использовать оператор ПОДОБНО в запросе 1С и избежать синтаксических ошибок?

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

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

Анализ синтаксических ошибок в тексте запроса

Рассмотрим исходный фрагмент кода, в котором была сделана попытка исключить задачи, содержащие определенный текст:


ЗапросЗадачиЗаПериод.Текст = "
    |ВЫБРАТЬ
    |    ЗадачаИсполнителя.Ссылка
    |ИЗ
    |    Задача.ЗадачаИсполнителя КАК ЗадачаИсполнителя
    |ГДЕ
    |    ЗадачаИсполнителя.Наименование НЕ ПОДОБНО %[ПЕРЕНАПРАВЛЕННАЯ ЗАДАЧА]%
    |    ЗадачаИсполнителя.ДатаВыполненияПланово МЕЖДУ &НачДата И &КонДата
    |    ЗадачаИсполнителя.Исполнитель = &Исполнитель";

В данном фрагменте допущено сразу несколько базовых синтаксических ошибок:

  1. Строковый литерал без кавычек: Текст шаблона поиска должен быть строковым литералом. Поскольку текст запроса задается строкой во встроенном языке, кавычки внутри текста запроса необходимо экранировать удвоением (""%Шаблон%"") либо передавать шаблон через параметр запроса.
  2. Некорректная конструкция отрицания: В языке запросов 1С отрицание НЕ пишется перед всем выражением проверки условия: НЕ Поле ПОДОБНО &Шаблон, а не Поле НЕ ПОДОБНО.
  3. Отсутствие логических связок: Условия в секции ГДЕ обязательно должны разделяться логическими операторами И или ИЛИ. Простой перенос строки не является разделителем условий в языке запросов.

Логическая ошибка: работа с квадратными скобками и экранирование

Проанализируем скрытую проблему, с которой сталкиваются при поиске подстрок, содержащих символы [ и ]. В языке запросов 1С квадратные скобки внутри шаблона ПОДОБНО являются служебными символами. Они задают перечисление диапазона символов (поиск любого одиночного символа из перечисленных внутри скобок).

Если написать шаблон "%[ПЕРЕНАПРАВЛЕННАЯ ЗАДАЧА]%", СУБД будет искать строки, в которых встречается хотя бы одна из букв (П, Е, Р, ...) или пробел, а не целую фразу в скобках. В результате условие отсечет практически все записи.

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


ЗапросЗадачиЗаПериод = Новый Запрос;
ЗапросЗадачиЗаПериод.Текст = "
    |ВЫБРАТЬ
    |    ЗадачаИсполнителя.Ссылка КАК Ссылка
    |ИЗ
    |    Задача.ЗадачаИсполнителя КАК ЗадачаИсполнителя
    |ГДЕ
    |    НЕ ЗадачаИсполнителя.Наименование ПОДОБНО &ШаблонПоиска СПЕЦСИМВОЛ ""/""
    |    И ЗадачаИсполнителя.ДатаВыполненияПланово МЕЖДУ &НачДата И &КонДата
    |    И ЗадачаИсполнителя.Исполнитель = &Исполнитель";

ЗапросЗадачиЗаПериод.УстановитьПараметр("НачДата", НачалоДня(ТекущаяДата()));
ЗапросЗадачиЗаПериод.УстановитьПараметр("КонДата", КонецДня(ТекущаяДата()));
ЗапросЗадачиЗаПериод.УстановитьПараметр("Исполнитель", ТекущийПользователь);
// Экранируем спецсимволы символом "/"
ЗапросЗадачиЗаПериод.УстановитьПараметр("ШаблонПоиска", "%/[ПЕРЕНАПРАВЛЕННАЯ ЗАДАЧА/]");

Посмотрим на правила использования экранирования:

  1. В качестве спецсимвола объявляется любой символ, например / или \.
  2. Спецсимвол ставится непосредственно перед каждым служебным знаком, который должен трактоваться буквально.
  3. Передача шаблона через УстановитьПараметр() соответствует стандартам разработки 1С и исключает ошибки форматирования кавычек в тексте запроса.

Проблемы производительности оператора ПОДОБНО

Выясним причину, почему использование оператора ПОДОБНО с маской %текст% считается нежелательным на больших объемах данных:

  1. Невозможность использования индексов: Если символ % стоит в начале шаблона, СУБД не может использовать индекс по полю Наименование. Это приводит к полному сканированию таблицы (Table Scan / Index Scan), что многократно замедляет выполнение запроса при росте количества записей.
  2. Совместимость с СУБД: Конструкции со скобками [...] поддерживаются не всеми СУБД (например, не поддерживаются в IBM DB2), а в PostgreSQL некорректно экранированные скобки могут приводить к ошибкам синтаксиса регулярных выражений на уровне базы данных.

Правильное архитектурное решение

Попытка хранить признаки состояния объекта (например, признак перенаправления задачи) внутри текстового поля Наименование нарушает первую нормальную форму реляционных баз данных и приводит к необходимости написания неэффективных запросов.

Рассмотрим правильные варианты реализации задачи:

  1. Добавление отдельного реквизита: В объект Задача.ЗадачаИсполнителя добавляется реквизит Перенаправлена с типом Булево. По данному реквизиту можно построить простой и быстрый отбор:
    
    |ГДЕ
    |    НЕ ЗадачаИсполнителя.Перенаправлена
    |    И ЗадачаИсполнителя.ДатаВыполненияПланово МЕЖДУ &НачДата И &КонДата
    |    И ЗадачаИсполнителя.Исполнитель = &Исполнитель
    
  2. Использование типовых механизмов (БСП): Если конфигурация находится на поддержке без возможности изменения структуры метаданных, признак можно хранить через механизм дополнительных реквизитов и сведений.
  3. Использование регистра сведений: Создание независимого непериодического регистра сведений для фиксации перенаправленных задач позволяет выполнять соединение или проверку через условие НЕ В (...) без перебора текстовых полей.
← На главную