При переходе с MS SQL Server на PostgreSQL разработчики часто сталкиваются с ситуацией, когда привычные и годами работающие запросы внезапно перестают возвращать данные. Одной из самых коварных проблем является использование оператора ПОДОБНО (LIKE) в сочетании с конкатенацией строк (сложением через "+") непосредственно в тексте запроса. В этой статье мы подробно разберем, почему возникает эта ошибка, как она связана с архитектурой СУБД и как правильно писать кроссплатформенные запросы, соответствующие стандартам 1С.
Рассмотрим классическую ситуацию. Разработчик хочет найти номенклатуру, в названии которой встречается определенный шаблон, обрамленный фиксированным текстом. В коде это часто выглядит так:
Запрос.Текст = "ВЫБРАТЬ
| Номенклатура.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Наименование ПОДОБНО ""%Группа "" + &Шаблон + ""%""";
На MS SQL Server этот запрос отработает без проблем. Однако при выполнении того же кода в базе на PostgreSQL результат окажется пустым, даже если в базе точно есть подходящие записи. Разберем по шагам причины такого поведения:
CHAR и VARCHAR. При сложении строк разной длины или параметров внутри запроса транслятор 1С может преобразовывать их таким образом, что в итоговый шаблон поиска добавляются невидимые завершающие пробелы. В результате вместо поиска по строке %Группа А% СУБД ищет %Группа А %, что не соответствует реальным данным.+ для сложения строк, в то время как PostgreSQL использует стандартный SQL-оператор ||. Платформа 1С берет на себя трансляцию этих знаков, но при сложных вложенных конструкциях внутри ПОДОБНО логика формирования итогового SQL-выражения может приводить к некорректной интерпретации спецсимволов.NULL всегда дает NULL. Если параметр &Шаблон по какой-то причине окажется не определен, все условие ГДЕ превратится в ПОДОБНО NULL, и результат будет пустым.Согласно стандартам разработки 1С, параметры запроса должны передаваться в максимально "готовом" виде. Это гарантирует предсказуемое поведение на любой СУБД и оптимальную производительность. Выясним, как переписать наш запрос правильно.
Вместо того чтобы заставлять СУБД складывать строки во время выполнения поиска, мы должны подготовить итоговую строку поиска заранее в коде 1С и передать её как один параметр.
Рассмотрим правильный пример реализации:
// Подготавливаем шаблон поиска заранее
ПолныйШаблон = "%Группа " + СтрокаШаблона + "%";
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| Номенклатура.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Наименование ПОДОБНО &ПолныйШаблон";
Запрос.УстановитьПараметр("ПолныйШаблон", ПолныйШаблон);
Результат = Запрос.Выполнить();
Такой подход полностью решает проблему совместимости с PostgreSQL по следующим причинам:
%).Важно понимать, что использование вычислений (таких как ВЫРАЗИТЬ, ПОДСТРОКА или конкатенация строк +) в секции ГДЕ или ПОДОБНО крайне негативно сказывается на скорости работы. Проанализируем ситуацию: когда СУБД видит конструкцию ПОДОБНО "%строка" + &Параметр, она вынуждена вычислять значение выражения для каждой строки таблицы перед сравнением.
Это приводит к полному сканированию таблицы (Full Table Scan), даже если у вас созданы идеальные индексы. Передача готового параметра позволяет серверу базы данных заранее построить план выполнения и минимизировать нагрузку на дисковую подсистему.
При работе с PostgreSQL стоит помнить об управляющих символах. Если ваш &Шаблон сам может содержать символы %, _ или обратный слэш \, их необходимо экранировать. В 1С для этого предусмотрено ключевое слово СПЕЦСИМВОЛ (ESCAPE).
Пример использования с экранированием:
// Допустим, мы ищем строку, содержащую реальный процент "%"
// Нам нужно заменить "%" на "/%" в параметре и указать "/" как спецсимвол
ПоискСПроцентом = "%" + СтрЗаменить(ТекстПоиска, "%", "/%") + "%";
Запрос.Текст = "ВЫБРАТЬ Ссылка ИЗ Справочник.Товары
|ГДЕ Наименование ПОДОБНО &Шаблон СПЕЦСИМВОЛ ""/""";
Запрос.УстановитьПараметр("Шаблон", ПоискСПроцентом);
Проблема с ПОДОБНО на PostgreSQL — это не баг платформы, а следствие различий в реализации стандартов SQL разными производителями СУБД. Для того чтобы ваш код работал стабильно и быстро в любой среде, следуйте простым правилам:
Запрос.Выполнить().ПОДОБНО для обеспечения кроссплатформенности.Соблюдение этих рекомендаций позволит вам избежать "поломок" при миграции баз данных и обеспечит высокую скорость работы ваших информационных систем на базе PostgreSQL.