Как использовать поле таблицы как подстроку для параметра в запросе 1С?

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

Разберем нестандартную, но встречающуюся на практике задачу. Представим ситуацию: мы передаем в запрос длинную строку текста (например, назначение платежа или список наименований через запятую) и хотим выбрать из справочника только те элементы, наименования которых содержатся в этой переданной строке. То есть нам нужен "обратный" поиск, где искомым шаблоном выступает само поле базы данных, а текстом для поиска — параметр.

Рассмотрим подробнее, как реализовать такой запрос, с какими критическими ограничениями платформы и СУБД мы столкнемся, и проанализируем более эффективные альтернативные решения.

Решение "в лоб" с помощью оператора ПОДОБНО

Для проверки вхождения подстроки в строку в языке запросов 1С используется оператор ПОДОБНО. Чтобы проверить, содержится ли наименование справочника в строке параметра, мы должны поместить параметр слева, а поле таблицы с добавленными символами % — справа.

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


ВЫБРАТЬ
    Валюты.Наименование КАК Наименование
ИЗ
    Справочник.Валюты КАК Валюты
ГДЕ
    &Парам ПОДОБНО "%" + Валюты.Наименование + "%"

В данном случае, если параметр Парам содержит строку "USD EUR RUB", а в справочнике есть элементы с наименованиями "USD" и "EUR", запрос вернет именно их. Если вы формируете текст запроса динамически в коде (собираете строку), не забывайте экранировать кавычки: &Парам ПОДОБНО ""%"" + Таблица.Наименование + ""%"".

Почему этот метод опасен: ограничения платформы и СУБД

Проанализируем подводные камни такого решения. Несмотря на то, что код выше отработает на файловой базе или Microsoft SQL Server, его использование крайне не рекомендуется по ряду причин:

  1. Нарушение стандартов 1С и совместимости. По стандартам разработки 1С, правым операндом для операции ПОДОБНО должен выступать только строковый литерал или параметр. Использование поля таблицы справа может привести к синтаксической ошибке на уровне некоторых СУБД (например, IBM DB2).
  2. Катастрофическое падение производительности. Использование символа % в начале шаблона отключает использование индексов базы данных. СУБД выполнит полное сканирование таблицы (Full Table Scan). Если в справочнике десятки тысяч элементов, система "повиснет".
  3. Ограничение на длину шаблона. Длина строки шаблона в СУБД обычно ограничена (часто это 1024 символа). Если параметр окажется длиннее, выполнение запроса завершится ошибкой.
  4. Проблема спецсимволов. Если в наименовании справочника случайно окажутся служебные символы регулярных выражений ([, ], ^, _, %), поиск сработает некорректно, а в PostgreSQL это может вызвать критическую ошибку invalid regular expression.

Альтернативные и безопасные способы решения

Посмотрим на более надежные методы решения этой задачи, которые сохранят производительность системы.

1. Использование массива и оператора "В"

Если ваша строка-параметр фактически состоит из конкретных слов, разделенных пробелами или запятыми, правильнее разбить её на массив до выполнения запроса с помощью функции СтрРазделить(). Затем передаем этот массив в запрос.


// В модуле 1С:
МассивИскомых = СтрРазделить(ПараметрСтрока, ", ", Ложь);
Запрос.УстановитьПараметр("МассивЗначений", МассивИскомых);

// В тексте запроса:
ГДЕ Таблица.Наименование В (&МассивЗначений)

Этот запрос отработает мгновенно, так как СУБД будет использовать индексы по полю Наименование.

2. Поиск встроенным языком 1С

Если мы заранее знаем, что справочник содержит небольшое количество элементов, мы можем выгрузить нужные данные запросом без тяжелых условий, а поиск выполнить при обходе выборки в цикле с использованием функции СтрНайти(). Это снимет нагрузку с сервера баз данных и перенесет её на сервер приложений.

3. Полнотекстовый поиск (ПТП)

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

4. Экранирование (если без ПОДОБНО не обойтись)

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

← На главную