При разработке механизмов поиска или загрузки данных из внешних источников (например, Excel) программисты часто сталкиваются с ситуацией, когда запрос, использующий оператор ПОДОБНО, не возвращает ожидаемых результатов. Ошибки могут крыться как в самом тексте запроса, так и в способе передачи параметров или обработке полученной выборки. В этой статье мы подробно разберем, как правильно реализовать поиск по части строки, проанализируем типичные ошибки и рассмотрим продвинутые приемы работы с текстовыми полями в языке запросов 1С.
Рассмотрим стандартную ситуацию: необходимо найти ссылку на номенклатуру по артикулу, который частично совпадает со значением из файла. Часто начинающие разработчики допускают ошибку, пытаясь вставить спецсимволы поиска (проценты) непосредственно в текст запроса или, наоборот, забывают их добавить в значение параметра. Проанализируем правильный подход к установке параметров.
Вариант 1: Правильная установка параметра в коде
Спецсимвол % (процент), означающий любое количество произвольных символов, должен быть частью строкового значения, которое передается в параметр запроса. Рассмотрим пример кода:
// Подготовка значения артикула (очистка от лишних пробелов)
АртикулПоиска = СокрЛП(Строка(Ячейка.Value));
Запрос = Новый Запрос;
// Добавляем проценты к значению переменной ПЕРЕД передачей в запрос
Запрос.УстановитьПараметр("Артикул", "%" + АртикулПоиска + "%");
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Артикул КАК Артикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Артикул ПОДОБНО &Артикул";
В данном случае, если в переменной АртикулПоиска находится значение "123", в параметр запроса уйдет строка "%123%". Это заставит систему искать все артикулы, которые содержат "123" в любой части строки.
Еще одна распространенная причина, по которой кажется, что запрос "ничего не выбирает" — это отсутствие обращения к результату. Выполнение метода Запрос.Выполнить().Выбрать() возвращает объект ВыборкаИзРезультатаЗапроса, который изначально не позиционирован ни на одной строке. Чтобы получить данные, необходимо вызвать метод Следующий().
Рассмотрим, как это должно выглядеть в рабочем коде:
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
// Обязательное условие для получения данных
Если Выборка.Следующий() Тогда
// Данные найдены, можно обращаться к полям
НайденнаяСсылка = Выборка.Ссылка;
Иначе
// Данные не найдены
Сообщить("Номенклатура с таким артикулом не обнаружена");
КонецЕсли;
Оператор ПОДОБНО поддерживает несколько служебных символов, которые позволяют гибко настраивать условия поиска. Выясним, какие возможности они предоставляют:
"А%" найдет все строки, начинающиеся на "А"."А_" найдет "А1", "АБ", но не найдет "А12"."А[123]" найдет "А1", "А2" или "А3"."А[^0-9]" найдет "АБ", но проигнорирует "А1".Проанализируем примеры использования масок непосредственно в параметрах:
// Начинается на Артикул
Запрос.УстановитьПараметр("МаскаНачало", Артикул + "%");
// Заканчивается на Артикул
Запрос.УстановитьПараметр("МаскаКонец", "%" + Артикул);
// Содержит Артикул внутри
Запрос.УстановитьПараметр("МаскаВнутри", "%" + Артикул + "%");
В сообщениях форума часто упоминается проблема, когда поиск не срабатывает из-за невидимых пробелов в строках. В современных версиях платформы (начиная с 8.3.8) мы можем использовать функции обработки строк прямо внутри запроса. Это значительно эффективнее, чем строить сложные конструкции ВЫБОР КОГДА.
Посмотрим, как можно очистить данные в запросе перед сравнением:
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| СОКРЛП(Номенклатура.Артикул) ПОДОБНО &Артикул";
Функция СОКРЛП() внутри запроса удалит пробелы в начале и в конце поля базы данных, что сделает поиск по части строки более надежным.
Иногда задача усложняется: нужно найти записи, где одно поле таблицы содержит значение другого поля этой же таблицы. Например, нужно сопоставить назначение платежа с номером счета. Если версия платформы позволяет использовать конкатенацию в условиях (секция ГДЕ), мы можем написать следующий код:
Запрос.Текст =
"ВЫБРАТЬ
| Платежи.Ссылка
|ИЗ
| Документ.ПлатежноеПоручение КАК Платежи
|ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.СчетНаОплату КАК Счета
|ПО (Платежи.НазначениеПлатежа ПОДОБНО ""%"" + Счета.Номер + ""%"")";
Важный нюанс: Если такой запрос вызывает ошибку "Недостаточно памяти" или выполняется слишком долго, это означает, что СУБД не может эффективно использовать индексы для такого соединения. В этом случае рекомендуется использовать временные таблицы и полнотекстовый поиск или выполнять сопоставление в коде после получения данных.
Разберем важный технический аспект: как оператор ПОДОБНО влияет на скорость работы системы.
Помните: поиск с маской в начале строки (например, ПОДОБНО "123%") позволяет SQL-серверу использовать индекс по этому полю. Однако поиск с процентом в начале (ПОДОБНО "%123%") всегда приводит к полному сканированию таблицы (Full Scan). Если ваш справочник Номенклатура содержит сотни тысяч записей, такой запрос может существенно замедлить работу базы данных.
Для повышения производительности на больших объемах данных рассмотрите следующие альтернативы:
Подводя итог, можно сказать, что оператор ПОДОБНО является мощным инструментом, требующим внимательного отношения к передаваемым параметрам и понимания того, как работает выборка в языке 1С. Правильное сочетание строковых функций и корректная обработка результата Следующий() гарантируют стабильную работу ваших алгоритмов поиска.