Разработка и Конфигурация · 12 мин
Как сравнить строки в запросе 1С
Способы сравнения строк в запросе 1С: операторы равенства, ПОДОБНО, функции ВЫРАЗИТЬ и ПОДСТРОКА, учёт регистра и пробелов, типичные ошибки при сравнении.
Сравнение строк — одна из самых частых операций при написании запросов в 1С, и именно здесь разработчики чаще всего получают неожиданные результаты. Запрос не находит контрагента, хотя он точно есть в базе, условие по наименованию не срабатывает, а отбор «теряет» часть данных. Причина почти всегда в деталях: лишние пробелы, различие длины строк, регистр символов или неправильно выбранный оператор.
В языке запросов 1С доступно несколько способов сравнения строк: точное равенство через знак «=», шаблонный поиск через оператор ПОДОБНО, а также функции ПОДСТРОКА, ВЫРАЗИТЬ и СОКРЛ для подготовки значений перед сравнением. Каждый способ имеет свои условия применения и ограничения.
Ниже разобраны все основные приёмы сравнения строк в запросе 1С с примерами кода, типичными ошибками и способами проверки результата. Материал применим к управляемым приложениям на платформе 8.3, но большинство приёмов работает и на более ранних версиях.
Точное сравнение строк через оператор равенства
Самый простой способ сравнить строку в запросе 1С — использовать оператор «=» в секции ГДЕ. Запрос вернёт только те записи, где значение поля полностью совпадает с указанной строкой:
ВЫБРАТЬ
Контрагенты.Ссылка
ИЗ
Справочник.Контрагенты КАК Контрагенты
ГДЕ
Контрагенты.Наименование = "ООО Ромашка"
Здесь кроется первая тонкость: сравнение выполняется с учётом длины строки, заданной в метаданных. Если реквизит «Наименование» имеет тип Строка(100), а вы сравниваете его со строкой другой длины, платформа дополняет значения пробелами, и результат зависит от настроек базы данных. На практике это означает, что «ООО Ромашка» и «ООО Ромашка » с пробелом в конце могут считаться как равными, так и разными в зависимости от СУБД.
Вторая тонкость — регистр символов. В большинстве конфигураций сравнение строк в запросе 1С нечувствительно к регистру: «ромашка» и «Ромашка» будут равны. Однако это поведение определяется настройками сортировки базы данных (collation), и в отдельных случаях, особенно при нестандартной установке MS SQL или PostgreSQL, сравнение может оказаться регистрозависимым.
Поиск по шаблону с оператором ПОДОБНО
Когда нужно найти не точное совпадение, а строки, содержащие фрагмент текста, используется оператор ПОДОБНО. Он работает с двумя специальными символами: «%» заменяет любое количество любых символов, «_» — ровно один произвольный символ.
ВЫБРАТЬ
Номенклатура.Ссылка
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Наименование ПОДОБНО "%кабель%"
Такой запрос найдёт и «Кабель ВВГ 3x2.5», и «Провод-кабель монтажный», и «КАБЕЛЬНЫЙ лоток». Если нужно найти строки, начинающиеся с определённого текста, шаблон выглядит как "Кабель%", а заканчивающиеся — "%кабель".
Экранирование спецсимволов
Если в искомом тексте сами встречаются символы % или _, их нужно экранировать через параметр СПЕЦСИМВОЛ. Например, чтобы найти товар со скидкой «10%» в наименовании:
ГДЕ
Номенклатура.Наименование ПОДОБНО "%10~%%" СПЕЦСИМВОЛ "~"
Здесь символ «~» объявлен экранирующим, и последовательность «~%» воспринимается как обычный знак процента, а не как шаблон.
Сравнение строк разной длины через ВЫРАЗИТЬ
Частая ситуация: нужно сравнить поле типа Строка(150) с параметром или другим полем типа Строка(50). Из-за разницы в длине и дополняющих пробелах сравнение может работать некорректно. Решение — функция ВЫРАЗИТЬ, которая приводит значение к нужному типу и длине:
ВЫБРАТЬ
Данные.Поле1
ИЗ
РегистрСведений.Данные КАК Данные
ГДЕ
ВЫРАЗИТЬ(Данные.Поле1 КАК СТРОКА(50)) = &СтрокаПоиска
Функция ВЫРАЗИТЬ также незаменима при работе с полями неограниченной длины (Строка(0)). Такие поля хранятся как текст и не всегда доступны для сравнения напрямую. Приведение к фиксированной длине, например ВЫРАЗИТЬ(Комментарий КАК СТРОКА(200)), делает их сравнимыми, но помните: всё, что длиннее указанного предела, будет обрезано.
Важно понимать, что ВЫРАЗИТЬ в условии ГДЕ, как и ПОДОБНО с лидирующим процентом, отключает использование индекса. Если поле входит в индекс, а вы оборачиваете его функцией, СУБД будет сканировать таблицу целиком.
Учёт пробелов и функция СОКРЛ
Данные в базе часто содержат лишние пробелы: они попадают при копировании из Excel, при обменах, при ручном вводе. Строка «Иванов И.И.» и «Иванов И.И. » с пробелом в конце для оператора равенства могут оказаться разными значениями. Для очистки используйте функцию СОКРЛ, которая убирает незначащие пробелы слева и справа:
ГДЕ
СОКРЛ(Сотрудники.ФИО) = СОКРЛ(&ФИОПараметр)
Однако правильнее не латать каждый запрос функциями, а устранять проблему в данных. Если поле регулярно используется для сравнения и отборов, стоит один раз выполнить обработку, очищающую значения от лишних пробелов, и добавить СОКРЛ в момент записи данных (например, в обработчике ПередЗаписью). Тогда запросы останутся простыми и быстрыми.
Отдельный случай — неразрывные пробелы и другие невидимые символы, которые приходят из внешних источников. СОКРЛ их не удаляет. Если сравнение упорно не работает, хотя строки визуально одинаковы, проверьте коды символов: встроенная функция КодСимвола в языке 1С поможет найти «невидимую» разницу.
Если запрос не находит заведомо существующую строку, выведите это поле в консоль запросов вместе с функцией ДЛИНАСТРОКИ — нет, такой функции в языке запросов нет, поэтому проще выгрузить значение и проверить его длину уже в коде через СтрДлина(). Разница длин сразу укажет на лишние пробелы или невидимые символы.
Сравнение части строки: ПОДСТРОКА и ВЫБОР
Иногда сравнивать нужно не всю строку, а её часть — например, первые символы артикула или код из составного номера. Для этого служит функция ПОДСТРОКА:
ВЫБРАТЬ
Товары.Ссылка
ИЗ
Справочник.Номенклатура КАК Товары
ГДЕ
ПОДСТРОКА(Товары.Артикул, 1, 3) = "АВТ"
Запрос выберет все товары, артикул которых начинается с «АВТ». Функция принимает строку, начальную позицию (нумерация с единицы) и количество символов.
Для сложных условий сравнения удобен оператор ВЫБОР, который позволяет сопоставить строку с несколькими значениями и вернуть результат по условию:
ВЫБОР
КОГДА ПОДСТРОКА(Товары.Артикул, 1, 1) = "А"
ТОГДА "Автотовары"
КОГДА ПОДСТРОКА(Товары.Артикул, 1, 1) = "З"
ТОГДА "Запчасти"
ИНАЧЕ "Прочее"
КОНЕЦ КАК Категория
Такой приём используют для группировки данных в отчётах по строковым признакам, когда отдельного реквизита-категории в справочнике нет.
Сравнение способов
Точное совпадение, самый быстрый вариант, использует индекс. Требует совпадения длины и чистоты данных от пробелов
Поиск по началу строки, на части СУБД может использовать индекс. Не подходит для поиска в середине строки
Поиск вхождения в любом месте строки. Всегда полное сканирование таблицы, на больших данных работает медленно
Сравнение фрагмента строки фиксированной позиции. Индекс не используется, но поведение предсказуемо
Сравнение с очисткой пробелов. Спасает при грязных данных, но отключает индекс и замедляет запрос
Передача строки для сравнения через параметр
В реальном коде строка для сравнения почти всегда передаётся в запрос через параметр, а не вписывается в текст запроса. Это и безопаснее, и удобнее:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Контрагенты.Ссылка
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| Контрагенты.Наименование ПОДОБНО &Шаблон";
Запрос.УстановитьПараметр("Шаблон", "%" + СтрокаПоиска + "%");
Результат = Запрос.Выполнить().Выбрать();
Обратите внимание: символы % добавляются к параметру в коде, а не в тексте запроса. Так проще управлять шаблоном — например, искать только по началу строки или по точному совпадению в зависимости от настроек пользователя.
Перед передачей параметра полезно выполнить СокрЛП(СтрокаПоиска) в коде — это уберёт случайные пробелы, которые пользователь мог захватить при копировании. Если пользовательский ввод может содержать символы % и _, а искать их нужно буквально, экранируйте их в коде перед установкой параметра и добавьте СПЕЦСИМВОЛ в текст запроса.
- 1Воспроизведите условие в консоли запросов на тестовой базе с реальными данными
- 2Проверьте тип и длину сравниваемого поля в конфигураторе — совпадает ли с типом параметра
- 3Выведите значение поля без условий и проверьте его на пробелы и невидимые символы
- 4Приведите обе стороны сравнения к одному типу через ВЫРАЗИТЬ и при необходимости СОКРЛ
- 5Сравните время выполнения запроса до и после изменений — убедитесь, что не потеряли индекс
Производительность и проверка результата
Главное правило производительности при сравнении строк: условие должно позволять СУБД использовать индекс. Для этого поле в условии не должно быть обёрнуто в функции, а шаблон ПОДОБНО не должен начинаться с символа %. Если соблюсти это невозможно — например, нужен поиск подстроки в любом месте — ограничьте выборку дополнительными индексированными условиями: периодом, организацией, владельцем.
Проверить корректность сравнения помогает простой приём: выполните запрос без условия, но с вычисляемым полем-результатом сравнения. Например, выведите ВЫБОР КОГДА Наименование = &Строка ТОГДА "Совпало" ИНАЧЕ "Нет" КОНЕЦ рядом с самим наименованием. Так вы сразу увидите, какие значения не совпали и почему.
Как проверить результат
Запрос находит все ожидаемые строки, включая варианты с разным регистром
Часть заведомо подходящих записей не возвращается — проверяйте пробелы и длину строки
Запрос отрабатывает за доли секунды или несколько секунд
Запрос выполняется десятки секунд — вероятно, условие не использует индекс
Результат одинаков в обеих средах
Результаты различаются — дело в настройках сравнения строк СУБД, нужно явное приведение через ВЫРАЗИТЬ
Частые вопросы о сравнении строк в запросе 1С
Почему условие «=» не находит строку, которая точно есть в базе?
Чаще всего причина в лишних пробелах, невидимых символах или различии длины строк. Проверьте значение через СокрЛП в коде, сравните длину через СтрДлина и приведите обе стороны к одному типу функцией ВЫРАЗИТЬ. Также убедитесь, что сравниваете строку со строкой, а не с числом или ссылкой.
Учитывается ли регистр букв при сравнении строк в запросе?
В типовых настройках — нет, сравнение регистронезависимое, и «Абв» равно «абв». Но это поведение определяется collation базы данных, и в нестандартных конфигурациях СУБД регистр может учитываться. Если нужна гарантия, проверяйте запрос именно на той базе, где он будет работать.
Как найти строки, содержащие символ процента?
Используйте экранирование: добавьте в условие ПОДОБНО конструкцию СПЕЦСИМВОЛ, например ПОДОБНО "%~%%" СПЕЦСИМВОЛ "~". Тогда тильда экранирует знак процента, и он будет воспринят как обычный символ, а не как элемент шаблона.
Можно ли сравнить поле типа Строка неограниченной длины?
Напрямую — не всегда, такие поля хранятся иначе и могут быть недоступны для сравнения. Используйте ВЫРАЗИТЬ(Поле КАК СТРОКА(N)), указав достаточную длину. Учтите, что содержимое сверх указанной длины будет отрезано, поэтому выбирайте N с запасом.
Что быстрее: ПОДОБНО или ПОДСТРОКА с равенством?
Для поиска по началу строки предпочтительнее ПОДОБНО "текст%" — на части СУБД это условие может использовать индекс. ПОДСТРОКА всегда отключает индекс, так как к полю применяется функция. На небольших таблицах разница незаметна, на больших — критична.
Как сравнить строки без учёта пробелов внутри, а не только по краям?
Стандартной функции удаления всех пробелов в языке запросов нет — СОКРЛ убирает только крайние. Если нужно игнорировать пробелы внутри строки, обработку придётся выполнять в коде 1С до передачи значения в запрос, либо заранее нормализовать данные в базе отдельной обработкой.
Что важно запомнить
Для точного сравнения строк используйте «=», для поиска по шаблону — ПОДОБНО с % и _. Приводите значения к одной длине через ВЫРАЗИТЬ и очищайте пробелы через СОКРЛ. Помните: функции вокруг поля и шаблон "%текст%" отключают индекс, поэтому на больших таблицах ограничивайте выборку дополнительными условиями и проверяйте запросы на реальной среде.