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

Разработка и Конфигурация · 11 мин

Как заменить символы в строке в запросе 1С

Как заменить символы в строке в запросе 1С: функция СТРЗАМЕНИТЬ, примеры синтаксиса, обходные пути для старых платформ, типичные ошибки и проверка результата.

Задача замены символов в строке прямо в запросе возникает часто: нужно убрать пробелы из артикула, заменить дефисы в номере документа, нормализовать телефонный номер для сравнения или очистить наименование от служебных символов. В языке запросов 1С для этого предусмотрена функция СТРЗАМЕНИТЬ, но она доступна не во всех версиях платформы, поэтому важно понимать и обходные пути.

Главное ограничение языка запросов — отсутствие циклов и регулярных выражений. Замена выполняется только «в лоб»: указывается исходная строка, искомая подстрока и подстрока замены. Если нужно убрать несколько разных символов, приходится вкладывать вызовы функции друг в друга, что быстро делает текст запроса громоздким.

Ниже разобран синтаксис функции, практические примеры, способы работы на старых платформах без СТРЗАМЕНИТЬ, а также типичные ошибки, из-за которых запрос возвращает пустой результат или падает с ошибкой.

Функция СТРЗАМЕНИТЬ: синтаксис и требования к версии

Функция СТРЗАМЕНИТЬ появилась в языке запросов начиная с платформы 8.3.6. Если конфигурация работает на более ранней версии, запрос с этой функцией не пройдёт проверку и выдаст ошибку «Функция не найдена». Перед использованием проверьте версию платформы, на которой реально эксплуатируется база, а не только ту, что установлена у разработчика.

Синтаксис функции:

СТРЗАМЕНИТЬ(ИсходнаяСтрока, ПодстрокаПоиска, ПодстрокаЗамены)

Все три параметра обязательны и должны иметь строковый тип. Функция заменяет все вхождения искомой подстроки, а не только первое. Если подстрока поиска не найдена, возвращается исходная строка без изменений — это удобно, так как не требует предварительной проверки.

Пример простого запроса, убирающего пробелы из артикула:

ВЫБРАТЬ

СТРЗАМЕНИТЬ(Номенклатура.Артикул, " ", "") КАК АртикулБезПробелов

ИЗ

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

Типовые примеры: пробелы, дефисы, скобки

Удаление символа

Чтобы удалить символ, в третьем параметре передаётся пустая строка. Так обрабатывают телефоны, ИНН, артикулы:

СТРЗАМЕНИТЬ(Контрагенты.Телефон, "-", "") КАК ТелефонБезДефисов

Замена одного символа на другой

Классический случай — замена десятичного разделителя или разделителя в номере:

СТРЗАМЕНИТЬ(Документ.НомерВходящего, "/", "-") КАК НомерДляПечати

Несколько замен через вложенные вызовы

Один вызов заменяет одну подстроку. Чтобы убрать из телефона скобки, пробелы и дефисы, вызовы вкладываются друг в друга:

СТРЗАМЕНИТЬ(

СТРЗАМЕНИТЬ(

СТРЗАМЕНИТЬ(Контрагенты.Телефон, "(", ""),

")", ""),

" ", "") КАК ТелефонОчищенный

Вложенность выполняется изнутри наружу: сначала убираются открывающие скобки, затем закрывающие, затем пробелы. При трёх-четырёх уровнях запрос ещё читаем; если символов больше, разумнее перенести обработку в код.

bsl
ВЫБРАТЬ
	СТРЗАМЕНИТЬ(Номенклатура.Наименование, "  ", " ") КАК Наименование
ИЗ
	Справочник.Номенклатура КАК Номенклатура
ГДЕ
	НЕ Номенклатура.ПометкаУдаления

Замена символов в условии ГДЕ и при соединении

Функцию можно использовать не только в списке выборки, но и в условиях отбора — это частый приём при поиске дублей по «грязным» данным:

ВЫБРАТЬ

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

ИЗ

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

ГДЕ

СТРЗАМЕНИТЬ(Контрагенты.Наименование, " ", "") = &НормализованноеИмя

Так же функция применяется в условии соединения таблиц, когда ключи в двух источниках записаны в разном формате. Однако здесь есть важное ограничение: замена в условии отбора или соединения отключает использование индексов по этому полю. На больших таблицах (сотни тысяч записей) такой запрос будет сканировать таблицу целиком и выполняться заметно дольше.

Что делать на платформе ниже 8.3.6

Если СТРЗАМЕНИТЬ недоступна, есть два рабочих подхода.

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

ВЫБРАТЬ

ПОДСТРОКА(Документ.Номер, 1, 3) + "-" + ПОДСТРОКА(Документ.Номер, 4, 10) КАК НомерСДефисом

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

Второй, более универсальный путь — выполнить запрос без замены, а затем обработать результат во встроенном языке функцией СтрЗаменить() при обходе выборки или в цикле по таблице значений:

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

АртикулЧистый = СтрЗаменить(Выборка.Артикул, " ", "");

КонецЦикла;

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

Сравнение вариантов

СТРЗАМЕНИТЬ в запросе

Подходит для платформы 8.3.6 и новее; обработка на стороне СУБД, удобно для отбора и соединения. Ограничение — одна подстрока за вызов и потеря индексов в условиях.

СтрЗаменить в коде после запроса

Работает на любой версии платформы, позволяет сложную логику и регулярные выражения через дополнительные средства. Минус — лишний цикл и расход памяти на больших выборках.

ПОДСТРОКА + конкатенация

Единственный вариант внутри запроса на старых платформах. Годится только для строк фиксированной структуры с известными позициями символов.

Нестандартные и невидимые символы

На практике частая проблема — неразрывные пробелы, табуляции и символы переноса строки, которые визуально неотличимы от обычного пробела, но не совпадают с ним при сравнении. В запросе их можно указать через функцию СИМВОЛ() с кодом символа:

СТРЗАМЕНИТЬ(Номенклатура.Наименование, СИМВОЛ(160), " ") КАК Наименование

Здесь СИМВОЛ(160) — неразрывный пробел, который заменяется на обычный. Коды часто встречающихся невидимых символов:

СимволКодГде появляется
Неразрывный пробел160Копирование из Excel, веб-страниц, печатных форм
Табуляция9Импорт из табличных файлов
Перенос строки10Многострочные поля, выгрузки
Возврат каретки13Файлы, подготовленные в Windows

Для очистки многострочного текста от переводов строк обычно нужны две вложенные замены: сначала СИМВОЛ(13) на пустую строку, затем СИМВОЛ(10) на пробел или нужный разделитель.

Если замена «не срабатывает» хотя символ визуально присутствует, почти всегда дело в невидимом символе с другим кодом. Быстрый способ диагностики — встроенной функцией КодСимвола() в коде посмотреть коды подозрительных позиций строки, а затем использовать СИМВОЛ() с найденным кодом в запросе.
ПЗ
Практическое замечание

Проверка результата и типичные ошибки

После написания запроса проверьте его в консоли запросов на реальных данных, особенно на записях с «грязными» значениями. Полезно вывести рядом исходное и преобразованное поле, чтобы визуально сравнить результат:

ВЫБРАТЬ

Номенклатура.Артикул КАК Было,

СТРЗАМЕНИТЬ(Номенклатура.Артикул, " ", "") КАК Стало

ИЗ

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

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

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

Значения с искомым символом
Норма

Символ заменён или удалён во всех вхождениях

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

Заменено только частично или строка вернулась без изменений

Значения без искомого символа
Норма

Строки вернулись без изменений, без NULL

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

Появились NULL или пустые строки там, где были данные

Скорость выполнения
Норма

Запрос отрабатывает за приемлемое время на рабочем объёме

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

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

Типичные ошибки
01
Использование СТРЗАМЕНИТЬ на платформе ниже 8.3.6 — запрос падает с ошибкой «Функция не найдена»; проверяйте версию платформы базы, а не только конфигуратора разработчика.
02
Замена обычного пробела там, где в данных неразрывный пробел (код 160) — результат не меняется; используйте СИМВОЛ(160).
03
Попытка заменить сразу несколько разных символов одним вызовом — функция принимает только одну подстроку поиска, нужны вложенные вызовы.
04
Игнорирование регистра — замена не срабатывает для букв в другом регистре; применяйте ВРЕГ() или НРЕГ() перед заменой.
05
Замена в условии соединения больших таблиц — резкое падение производительности из-за отказа от индексов.

Когда замену лучше вынести из запроса

Язык запросов не единственное и не всегда лучшее место для обработки строк. Переносите замену во встроенный язык, если нужно заменить много разных символов (более трёх-четырёх), если логика зависит от условий, или если требуется регулярное выражение — в запросе их нет в принципе.

Если одна и та же нормализация нужна регулярно (например, поиск контрагентов по очищенному телефону), правильное архитектурное решение — хранить нормализованное значение в отдельном реквизите, заполнять его при записи объекта и индексировать. Тогда запросы остаются простыми и быстрыми, а замена выполняется один раз при записи, а не при каждом чтении.

Маршрут решения

Как выбрать действие

Платформа 8.3.6 или новее, заменяется 1–3 символаИспользуйте СТРЗАМЕНИТЬ прямо в запросе
Платформа старше 8.3.6Выполните замену функцией СтрЗаменить() в коде после получения результата запроса
Нужно убрать невидимые символыИспользуйте СТРЗАМЕНИТЬ с СИМВОЛ(код), предварительно определив коды через КодСимвола()
Замена нужна в соединении больших таблицСоздайте нормализованный реквизит, заполняйте при записи и индексируйте его
Символов много или нужна сложная логикаОбрабатывайте строки во встроенном языке, а не в запросе
Итог

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

В запросе 1С символы заменяются функцией СТРЗАМЕНИТЬ (платформа 8.3.6 и новее): она заменяет все вхождения одной подстроки, чувствительна к регистру и не работает с индексами в условиях. Невидимые символы задаются через СИМВОЛ(код). На старых платформах и при сложной логике замену выполняют функцией СтрЗаменить() во встроенном языке после выполнения запроса.

Частые вопросы

Заменяет ли СТРЗАМЕНИТЬ все вхождения или только первое?

Функция заменяет все вхождения искомой подстроки в строке. Отдельного параметра для ограничения количества замен нет. Если нужно заменить только первое вхождение, придётся комбинировать ПОДСТРОКА с конкатенацией или выполнять обработку в коде.

Почему запрос с СТРЗАМЕНИТЬ выдаёт ошибку «Функция не найдена»?

Функция доступна в языке запросов начиная с платформы 8.3.6. Проверьте версию платформы, под которой запускается база (помощью «О программе» или через Метаданные.Версия в коде — точнее, ТекущаяВерсияПлатформы из системной информации). Если версия ниже, используйте СтрЗаменить() во встроенном языке после выполнения запроса.

Как убрать из строки сразу несколько разных символов?

Один вызов СТРЗАМЕНИТЬ обрабатывает одну подстроку. Для нескольких символов вызовы вкладывают друг в друга: внутренний результат передаётся первым параметром во внешний вызов. При количестве символов больше трёх-четырёх читабельнее сделать обработку в цикле по таблице результата функцией СтрЗаменить() в коде.

Замена не срабатывает, хотя символ точно есть в строке. В чём причина?

Чаще всего причина две: регистр букв не совпадает (замена регистрозависима) или в данных стоит невидимый символ с другим кодом — например, неразрывный пробел (код 160) вместо обычного. Определите фактический код символа функцией КодСимвола() в коде и используйте в запросе СИМВОЛ() с этим кодом.

Можно ли использовать СТРЗАМЕНИТЬ в параметре виртуальной таблицы?

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

Что вернёт СТРЗАМЕНИТЬ, если исходная строка NULL?

Если любой из параметров равен NULL, результатом будет NULL. При работе с необязательными строковыми реквизитами и левых соединениях оборачивайте поле в ЕСТЬNULL(Поле, "") до вызова замены, чтобы не потерять строки в результате.