К статье
Практический материал

Разработка и Конфигурация · 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)), делает их сравнимыми, но помните: всё, что длиннее указанного предела, будет обрезано.

Важно понимать, что ВЫРАЗИТЬ в условии ГДЕ, как и ПОДОБНО с лидирующим процентом, отключает использование индекса. Если поле входит в индекс, а вы оборачиваете его функцией, СУБД будет сканировать таблицу целиком.

Типичные ошибки
01
Сравнение строки неограниченной длины напрямую через «=» — в ряде ситуаций запрос завершается ошибкой или возвращает пустой результат; нужно ВЫРАЗИТЬ поле к фиксированной длине
02
Поиск по ПОДОБНО без учёта пробелов в данных: значение « Кабель» с пробелом в начале не найдётся шаблоном "Кабель%"
03
Сравнение строки с числом или ссылкой без явного приведения типов — запрос вернёт пустой результат без сообщения об ошибке
04
Оборачивание индексированного поля функцией в условии ГДЕ, из-за чего запрос на большой таблице начинает выполняться в десятки раз медленнее

Учёт пробелов и функция СОКРЛ

Данные в базе часто содержат лишние пробелы: они попадают при копировании из Excel, при обменах, при ручном вводе. Строка «Иванов И.И.» и «Иванов И.И. » с пробелом в конце для оператора равенства могут оказаться разными значениями. Для очистки используйте функцию СОКРЛ, которая убирает незначащие пробелы слева и справа:

ГДЕ

СОКРЛ(Сотрудники.ФИО) = СОКРЛ(&ФИОПараметр)

Однако правильнее не латать каждый запрос функциями, а устранять проблему в данных. Если поле регулярно используется для сравнения и отборов, стоит один раз выполнить обработку, очищающую значения от лишних пробелов, и добавить СОКРЛ в момент записи данных (например, в обработчике ПередЗаписью). Тогда запросы останутся простыми и быстрыми.

Отдельный случай — неразрывные пробелы и другие невидимые символы, которые приходят из внешних источников. СОКРЛ их не удаляет. Если сравнение упорно не работает, хотя строки визуально одинаковы, проверьте коды символов: встроенная функция КодСимвола в языке 1С поможет найти «невидимую» разницу.

Если запрос не находит заведомо существующую строку, выведите это поле в консоль запросов вместе с функцией ДЛИНАСТРОКИ — нет, такой функции в языке запросов нет, поэтому проще выгрузить значение и проверить его длину уже в коде через СтрДлина(). Разница длин сразу укажет на лишние пробелы или невидимые символы.
ПЗ
Практическое замечание

Сравнение части строки: ПОДСТРОКА и ВЫБОР

Иногда сравнивать нужно не всю строку, а её часть — например, первые символы артикула или код из составного номера. Для этого служит функция ПОДСТРОКА:

ВЫБРАТЬ

Товары.Ссылка

ИЗ

Справочник.Номенклатура КАК Товары

ГДЕ

ПОДСТРОКА(Товары.Артикул, 1, 3) = "АВТ"

Запрос выберет все товары, артикул которых начинается с «АВТ». Функция принимает строку, начальную позицию (нумерация с единицы) и количество символов.

Для сложных условий сравнения удобен оператор ВЫБОР, который позволяет сопоставить строку с несколькими значениями и вернуть результат по условию:

ВЫБОР

КОГДА ПОДСТРОКА(Товары.Артикул, 1, 1) = "А"

ТОГДА "Автотовары"

КОГДА ПОДСТРОКА(Товары.Артикул, 1, 1) = "З"

ТОГДА "Запчасти"

ИНАЧЕ "Прочее"

КОНЕЦ КАК Категория

Такой приём используют для группировки данных в отчётах по строковым признакам, когда отдельного реквизита-категории в справочнике нет.

Сравнение способов

Оператор «=»

Точное совпадение, самый быстрый вариант, использует индекс. Требует совпадения длины и чистоты данных от пробелов

ПОДОБНО с шаблоном "текст%"

Поиск по началу строки, на части СУБД может использовать индекс. Не подходит для поиска в середине строки

ПОДОБНО с шаблоном "%текст%"

Поиск вхождения в любом месте строки. Всегда полное сканирование таблицы, на больших данных работает медленно

ПОДСТРОКА + «=»

Сравнение фрагмента строки фиксированной позиции. Индекс не используется, но поведение предсказуемо

СОКРЛ + «=»

Сравнение с очисткой пробелов. Спасает при грязных данных, но отключает индекс и замедляет запрос

Передача строки для сравнения через параметр

В реальном коде строка для сравнения почти всегда передаётся в запрос через параметр, а не вписывается в текст запроса. Это и безопаснее, и удобнее:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Контрагенты.Ссылка

|ИЗ

| Справочник.Контрагенты КАК Контрагенты

|ГДЕ

| Контрагенты.Наименование ПОДОБНО &Шаблон";

Запрос.УстановитьПараметр("Шаблон", "%" + СтрокаПоиска + "%");

Результат = Запрос.Выполнить().Выбрать();

Обратите внимание: символы % добавляются к параметру в коде, а не в тексте запроса. Так проще управлять шаблоном — например, искать только по началу строки или по точному совпадению в зависимости от настроек пользователя.

Перед передачей параметра полезно выполнить СокрЛП(СтрокаПоиска) в коде — это уберёт случайные пробелы, которые пользователь мог захватить при копировании. Если пользовательский ввод может содержать символы % и _, а искать их нужно буквально, экранируйте их в коде перед установкой параметра и добавьте СПЕЦСИМВОЛ в текст запроса.

Порядок действий при отладке сравнения
  1. 1
    Воспроизведите условие в консоли запросов на тестовой базе с реальными данными
  2. 2
    Проверьте тип и длину сравниваемого поля в конфигураторе — совпадает ли с типом параметра
  3. 3
    Выведите значение поля без условий и проверьте его на пробелы и невидимые символы
  4. 4
    Приведите обе стороны сравнения к одному типу через ВЫРАЗИТЬ и при необходимости СОКРЛ
  5. 5
    Сравните время выполнения запроса до и после изменений — убедитесь, что не потеряли индекс

Производительность и проверка результата

Главное правило производительности при сравнении строк: условие должно позволять СУБД использовать индекс. Для этого поле в условии не должно быть обёрнуто в функции, а шаблон ПОДОБНО не должен начинаться с символа %. Если соблюсти это невозможно — например, нужен поиск подстроки в любом месте — ограничьте выборку дополнительными индексированными условиями: периодом, организацией, владельцем.

Проверить корректность сравнения помогает простой приём: выполните запрос без условия, но с вычисляемым полем-результатом сравнения. Например, выведите ВЫБОР КОГДА Наименование = &Строка ТОГДА "Совпало" ИНАЧЕ "Нет" КОНЕЦ рядом с самим наименованием. Так вы сразу увидите, какие значения не совпали и почему.

Контрольные точки

Как проверить результат

Количество найденных записей
Норма

Запрос находит все ожидаемые строки, включая варианты с разным регистром

Тревожный признак

Часть заведомо подходящих записей не возвращается — проверяйте пробелы и длину строки

Время выполнения на рабочем объёме данных
Норма

Запрос отрабатывает за доли секунды или несколько секунд

Тревожный признак

Запрос выполняется десятки секунд — вероятно, условие не использует индекс

Поведение в файловой и клиент-серверной базе
Норма

Результат одинаков в обеих средах

Тревожный признак

Результаты различаются — дело в настройках сравнения строк СУБД, нужно явное приведение через ВЫРАЗИТЬ

Частые вопросы о сравнении строк в запросе 1С

Почему условие «=» не находит строку, которая точно есть в базе?

Чаще всего причина в лишних пробелах, невидимых символах или различии длины строк. Проверьте значение через СокрЛП в коде, сравните длину через СтрДлина и приведите обе стороны к одному типу функцией ВЫРАЗИТЬ. Также убедитесь, что сравниваете строку со строкой, а не с числом или ссылкой.

Учитывается ли регистр букв при сравнении строк в запросе?

В типовых настройках — нет, сравнение регистронезависимое, и «Абв» равно «абв». Но это поведение определяется collation базы данных, и в нестандартных конфигурациях СУБД регистр может учитываться. Если нужна гарантия, проверяйте запрос именно на той базе, где он будет работать.

Как найти строки, содержащие символ процента?

Используйте экранирование: добавьте в условие ПОДОБНО конструкцию СПЕЦСИМВОЛ, например ПОДОБНО "%~%%" СПЕЦСИМВОЛ "~". Тогда тильда экранирует знак процента, и он будет воспринят как обычный символ, а не как элемент шаблона.

Можно ли сравнить поле типа Строка неограниченной длины?

Напрямую — не всегда, такие поля хранятся иначе и могут быть недоступны для сравнения. Используйте ВЫРАЗИТЬ(Поле КАК СТРОКА(N)), указав достаточную длину. Учтите, что содержимое сверх указанной длины будет отрезано, поэтому выбирайте N с запасом.

Что быстрее: ПОДОБНО или ПОДСТРОКА с равенством?

Для поиска по началу строки предпочтительнее ПОДОБНО "текст%" — на части СУБД это условие может использовать индекс. ПОДСТРОКА всегда отключает индекс, так как к полю применяется функция. На небольших таблицах разница незаметна, на больших — критична.

Как сравнить строки без учёта пробелов внутри, а не только по краям?

Стандартной функции удаления всех пробелов в языке запросов нет — СОКРЛ убирает только крайние. Если нужно игнорировать пробелы внутри строки, обработку придётся выполнять в коде 1С до передачи значения в запрос, либо заранее нормализовать данные в базе отдельной обработкой.

Итог

Что важно запомнить

Для точного сравнения строк используйте «=», для поиска по шаблону — ПОДОБНО с % и _. Приводите значения к одной длине через ВЫРАЗИТЬ и очищайте пробелы через СОКРЛ. Помните: функции вокруг поля и шаблон "%текст%" отключают индекс, поэтому на больших таблицах ограничивайте выборку дополнительными условиями и проверяйте запросы на реальной среде.