При разработке отчетов и запросов в системе 1С:Предприятие программисты часто сталкиваются с необходимостью текстового сопоставления данных. Типичный сценарий — проверка вхождения одной строки в другую с использованием оператора ПОДОБНО (аналога SQL-оператора LIKE). Однако попытки гибко настроить это сопоставление внутри самого запроса (например, привести ссылку к строке или использовать функцию представления) часто приводят к ошибкам синтаксического контроля платформы.
В этой статье мы подробно разберем, почему возникают ошибки вида «Неверные параметры ПОДОБНО», опровергнем популярные заблуждения с форумов и рассмотрим действительно работающие и эффективные методики решения этой задачи, особенно в контексте Системы компоновки данных (СКД).
Рассмотрим типичную ситуацию. Разработчик пытается написать в запросе следующее условие:
ГДЕ
ВТ.Наименование ПОДОБНО ПРЕДСТАВЛЕНИЕ(&МойСправочник)
Или его вариацию:
ГДЕ
ВТ.Наименование ПОДОБНО ВЫРАЗИТЬ(&МойСправочник КАК СТРОКА(10))
При попытке сохранения или выполнения такого запроса система незамедлительно выдаст ошибку. Давайте выясним причину такого поведения платформы. Согласно официальным стандартам разработки 1С (в частности, стандарту std726 «Особенности использования в запросах оператора ПОДОБНО»), синтаксис данного оператора строго ограничен:
<Выражение> [НЕ] ПОДОБНО <Литерал типа СТРОКА> [СПЕЦСИМВОЛ <Литерал типа СТРОКА>]
Это означает, что в правой части оператора ПОДОБНО (после самого ключевого слова) допускается использовать исключительно константный строковый литерал (например, "%Иванов%") или одиночный параметр запроса (например, &ШаблонИмени). Любые попытки вычислить строку «на лету» внутри запроса с помощью конкатенации (оператора +), использования функций типа ВЫРАЗИТЬ, ПОДСТРОКА или ПРЕДСТАВЛЕНИЕ в правой части оператора приведут к ошибке разбора запроса.
Важное предупреждение: на многих форумах (и в сообщении 7 данной ветки) предлагается якобы «работающее» решение:
ГДЕ ВТ.Наименование ПОДОБНО "%" + Выразить(&МойСправочник как Справочник.Номенклатура).Наименование + "%"
Проанализировав данную конструкцию, мы должны со всей ответственностью заявить: это решение синтаксически неверно и работать не будет! Платформа 1С не умеет динамически конкатенировать шаблоны поиска непосредственно внутри оператора ПОДОБНО в SQL-запросе.
---
Если вы выполняете запрос из кода на встроенном языке 1С, самым простым и правильным решением будет перенос операции формирования шаблона поиска из запроса в код подготовки параметров. Рассмотрим этот процесс по шагам.
Шаг 1. В тексте запроса мы оставляем чистый и понятный параметр:
ВЫБРАТЬ
Таблица.Ссылка КАК Ссылка,
Таблица.Наименование КАК Наименование
ИЗ
Справочник.Номенклатура КАК Таблица
ГДЕ
Таблица.Наименование ПОДОБНО &ШаблонПоиска
Шаг 2. Перед запуском запроса мы формируем значение этого параметра во встроенном языке, добавляя необходимые метасимволы (например, знак процента % для поиска по подстроке):
Запрос = Новый Запрос;
Запрос.Текст = ПолучитьТекстЗапроса(); // Загружаем наш текст запроса
// Получаем строковое представление или реквизит справочника
ТекстДляПоиска = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(&МойСправочник, "Наименование");
// Формируем шаблон с процентами с двух сторон для поиска вхождения
ШаблонСтроки = "%" + ТекстДляПоиска + "%";
Запрос.УстановитьПараметр("ШаблонПоиска", ШаблонСтроки);
Выборка = Запрос.Выполнить().Выбрать();
Этот метод полностью соответствует стандартам платформы, легко читается и не вызывает проблем при компиляции запроса СУБД.
---
Если вы разрабатываете отчет на базе Системы компоновки данных (СКД), то вам нет необходимости писать дополнительный код на встроенном языке. СКД предоставляет великолепные декларативные механизмы решения этой проблемы.
Мы можем перенести логику «склеивания» строки шаблона непосредственно в настройки параметров схемы компоновки данных. Выполним следующие действия:
ГДЕ ВТ.Наименование ПОДОБНО &ШаблонИмени.&ШаблонИмени и устанавливаем для него флаг «Ограничение доступности» (чтобы пользователь не вводил его вручную)."%" + Выразить(&МойСправочник, "Справочник.Номенклатура").Наименование + "%" (или просто "%" + ПРЕДСТАВЛЕНИЕ(&МойСправочник) + "%").
При генерации отчета СКД сама вычислит это выражение на сервере приложений, сформирует готовую строку (например, "%Товар%") и корректно передаст ее в параметры SQL-запроса.
Еще более изящный способ — отказаться от жесткого кодирования секции ГДЕ в запросе и доверить это механизму компоновки:
Наименование.ПОДОБНО "%...%").&МойСправочник.Наименование.Платформа автоматически сформирует оптимальный SQL-запрос, выполнив безопасное приведение типов и экранирование спецсимволов.
---
Бывают ситуации, когда вам нужно решить задачу исключительно в рамках одного запроса без привлечения кода и СКД. В этом случае на помощь приходит связывание таблиц. Мы можем соединить нашу исходную таблицу со справочником по условию равенства ссылки, а затем сопоставить наименования.
Рассмотрим пример внутреннего соединения:
ВЫБРАТЬ
ВТ.Ссылка КАК Ссылка,
ВТ.Наименование КАК Наименование
ИЗ
ВременнаяТаблица КАК ВТ
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК СпрНоменклатура
ПО СпрНоменклатура.Ссылка = &МойСправочник
И ВТ.Наименование ПОДОБНО "%" + СпрНоменклатура.Наименование + "%"
Обратите внимание: в секции ПО (или ГДЕ при связи таблиц) СУБД некоторых конфигураций позволяет выполнять операции сопоставления полей, однако этот метод имеет серьезные недостатки с точки зрения производительности.
---
При работе с текстовым поиском и оператором ПОДОБНО крайне важно помнить о физическом устройстве баз данных:
"%Текст%" (с процентом в начале строки) делает невозможным использование индексов СУБД. База данных будет вынуждена построчно перебрать всю физическую таблицу на диске. На больших таблицах (сотни тысяч и миллионы записей) это приведет к колоссальным задержкам и блокировкам. По возможности старайтесь выполнять поиск по началу строки: "Текст%" — в этом случае СУБД сможет задействовать индекс по наименованию.[ ], знак процента % или подчеркивание _), СУБД PostgreSQL может выдать критическую системную ошибку: ERROR: invalid regular expression.СПЕЦСИМВОЛ. Например:
ГДЕ ВТ.Наименование ПОДОБНО &ШаблонПоиска СПЕЦСИМВОЛ "~"
При этом в коде на встроенном языке необходимо предварительно экранировать служебные символы в искомой строке (заменяя их на ~%, ~_ и т.д.), для чего отлично подходят стандартные функции БСП, например, ОбщегоНазначения.СформироватьСтрокуДляПоискаВЗапросе().
Подводя итог, отметим, что наиболее гибким, безопасным и современным методом решения задачи сопоставления строк по параметру-ссылке является использование выражений параметров в СКД. Это разделяет логику формирования условий поиска и само выполнение запроса к базе данных, обеспечивая стабильную работу вашего приложения.