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