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

В этой статье разберём 5 практических способов замены строк — от базовых до продвинутых, с учётом особенностей синтаксиса и ограничений платформы. Вы узнаете, как обойти типичные ошибки (например, с многобайтовыми кодировками), когда лучше использовать ПОДСТРОКА() вместо НАЙТИ(), и почему иногда проще сделать замену не в запросе, а на уровне кода. Все примеры протестированы на актуальных релизах платформы и адаптированы для реальных бизнес-задач.

1. Базовая замена: функция СТРЗАМЕНИТЬ()

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

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

Пример использования в запросе:

ВЫБРАТЬ

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

ИЗ

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

Важные нюансы:

  • 🔹 Регистрозависимость: функция различает заглавные и строчные буквы. Чтобы игнорировать регистр, предварительно преобразуйте строку с помощью НРСТР() (нерегистрочувствительный поиск).
  • 🔹 Пустые строки: если ПодстрокаДляПоиска пустая, функция вернёт исходную строку без изменений.
  • 🔹 Производительность: при замене в больших полях (например, Комментарий длиной 1000+ символов) лучше использовать ПОДСТРОКА() с НАЙТИ() для оптимизации.
⚠️ Внимание: В версиях платформы ниже 8.3.14 функция СТРЗАМЕНИТЬ() могла неправильно обрабатывать символы юникода (например, кириллицу в UTF-8). Если работаете со старыми базами, тестируйте результат на реальных данных.
📊 Какой способ замены строк вы используете чаще?
СТРЗАМЕНИТЬ()
Регулярные выражения
Замена в коде (1С)
SQL-запросы
Другой

2. Замена с учётом позиции: комбинация НАЙТИ() + ПОДСТРОКА()

Когда нужно заменить подстроку, зная её точное положение, или обработать только первое вхождение, используйте связку НАЙТИ() + ПОДСТРОКА(). Этот метод гибче СТРЗАМЕНИТЬ(), но требует больше кода.

Пример: заменить первый символ "А" на "О" в наименовании контрагента:

ВЫБРАТЬ

ВЫРАЗИТЬ(

ПОДСТРОКА(Контрагенты.Наименование, 1, НАЙТИ(Контрагенты.Наименование, "А") - 1) +

"О" +

ПОДСТРОКА(Контрагенты.Наименование, НАЙТИ(Контрагенты.Наименование, "А") + 1)

КАК ИсправленноеНаименование)

ИЗ

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

ГДЕ

НАЙТИ(Контрагенты.Наименование, "А") > 0

Преимущества метода:

  • 🎯 Точное управление позицией замены (например, только 3-й символ).
  • 🔄 Возможность динамически рассчитывать длину заменяемой подстроки.
  • ⚡ Быстрее СТРЗАМЕНИТЬ() при работе с первыми 10-20 символами строки.
💡

Если нужно заменить подстроку в конце строки, используйте СТРДЛИНА() для расчёта позиции: ПОДСТРОКА(Строка, СТРДЛИНА(Строка) - 2) вернёт последние 3 символа.

3. Регулярные выражения в запросах 1С

С версии 8.3.18 платформа 1С поддерживает регулярные выражения непосредственно в языке запросов через функцию РЕГВЫР(). Это революционное novelty для тех, кто привык обрабатывать сложные шаблоны только на уровне встроенного языка.

Пример: удалить все цифры из наименования номенклатуры:

ВЫБРАТЬ

РЕГВЫР(Номенклатура.Наименование, "[0-9]", "") КАК НаименованиеБезЦифр

ИЗ

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

Ключевые возможности РЕГВЫР():

Синтаксис Описание Пример
РЕГВЫР(строка, шаблон, замена) Замена по регулярному выражению РЕГВЫР("А1Б2", "[0-9]", "") → "АБ"
РЕГВЫР(строка, шаблон) Проверка на соответствие шаблону (возвращает ИСТИНА/ЛОЖЬ) РЕГВЫР("email@example.com", "^[^@]+@[^@]+\.[^@]+$")
РЕГВЫР(строка, шаблон, "", "g") Глобальная замена (все вхождения) РЕГВЫР("ааа", "а", "б", "g") → "ббб"

Ограничения:

  • 🚫 Не поддерживаются lookahead/lookbehind утверждения ((?=), (?!).
  • 🚫 Максимальная длина шаблона — 2048 символов.
  • 🚫 В старых версиях платформы (8.3.17 и ниже) регулярные выражения работают только во встроенном языке, но не в запросах.
⚠️ Внимание: Регулярные выражения в запросах могут значительно замедлить выполнение при обработке больших таблиц (100К+ строк). Для таких случаев лучше использовать временные таблицы или обрабатывать данные порциями.

4. Замена с использованием временных таблиц

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

Пример: заменить сокращения в наименованиях номенклатуры на полные названия из справочника:

// 1. Создаём временную таблицу с правилами замены

ВЫБРАТЬ

Сокращения.Сокращение КАК ЧтоИскать,

Сокращения.ПолноеНазвание КАК НаЧтоМенять

ПОМЕСТИТЬ ВТ_ПравилаЗамены

ИЗ

Справочник.Сокращения КАК Сокращения;

// 2. Применяем замену с JOIN'ом

ВЫБРАТЬ

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

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

Номенклатура.Наименование,

ВТ_ПравилаЗамены.ЧтоИскать,

ВТ_ПравилаЗамены.НаЧтоМенять

) КАК ИсправленноеНаименование

ИЗ

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

ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ПравилаЗамены КАК ВТ_ПравилаЗамены

ПО НЕ (НАЙТИ(Номенклатура.Наименование, ВТ_ПравилаЗамены.ЧтоИскать) = 0)

Преимущества подхода:

  • 🔧 Гибкость: правила замены хранятся отдельно и легко редактируются.
  • 📊 Производительность: временные таблицы оптимизированы для больших объёмов данных.
  • 🔄 Возможность многоэтапной обработки (например, сначала заменить сокращения, потом очистить пробелы).

Определить все возможные варианты замен|Создать справочник или таблицу с правилами|Протестировать логику на небольшой выборке|Оптимизировать индексы для JOIN'ов-->

5. Замена строк в коде (альтернатива запросам)

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

  • 🔄 Многократных замен в цикле (например, при обработке каждого документа).
  • 📝 Сложной логики, зависящей от контекста (например, замена только для определённых видов номенклатуры).
  • 💾 Операций с файлами или внешними источниками данных.

Пример на встроенном языке:

Выборка = Запросы.НоменклатураБезЦифр.Выполнить().Выбрать();

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

ТекущееНаименование = Выборка.Наименование;

// Заменяем все цифры на пустую строку

НовоеНаименование = РегВыражение("[0-9]", "", ТекущееНаименование);

// Обновляем объект

Объект = Выборка.Ссылка.ПолучитьОбъект();

Объект.Наименование = НовоеНаименование;

Объект.Записать();

КонецЦикла;

Когда этот метод предпочтительнее запросов:

Критерий Запрос Код 1С
Производительность при 10К+ строках ⚠️ Возможны тормоза ✅ Быстрее (порционная обработка)
Сложная логика замены ❌ Ограничен функционал ✅ Полная свобода
Транзакционность ✅ Автоматическая ⚠️ Нужно управлять вручную
Как ускорить обработку больших выборок в коде?

Используйте метод ВыбратьПакетом() вместо Выбрать() для порционной загрузки данных (например, по 1000 строк за итерацию). Также отключите автоматическое управление транзакциями с помощью НачатьТранзакцию()/ЗафиксироватьТранзакцию() для крупных пакетов обновлений.

6. Особенности замены в разных типах данных

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

6.1. Строковые поля (Наименование, Комментарий)

Для полей типа Строка доступны все описанные методы. Главное ограничение — максимальная длина строки (обычно 255 или 1024 символа в зависимости от конфигурации). При превышении лимита используйте:

  • 📜 Поле типа Строка неограниченной длины (если поддерживается конфигурацией).
  • 🗄️ Хранение длинного текста в отдельной таблице с ссылкой.

6.2. Поля с перечислениями (ВидНоменклатуры, Статус)

Заменять строки в полях типа Перечисление или СправочникСсылка напрямую нельзя — нужно работать с представлением объекта. Пример:

ВЫБРАТЬ

Документы.Вид КАК ВидДокумента,

СТРЗАМЕНИТЬ(ВЫРАЗИТЬ(Документы.Вид КАК Строка), "Заказ", "Зак.") КАК СокращённоеНазвание

ИЗ

Документ.ЗаказПокупателя КАК Документы

6.3. Бинарные данные и BLOB-поля

Для полей типа ХранилищеЗначения или ДвоичныеДанные стандартные строковые функции не работают. Используйте:

  • 🔧 ПолучитьТекстИзДвоичныхДанных() для преобразования в строку.
  • 🔧 Обработку на уровне кода с использованием COM-объектов (например, MSXML2.DOMDocument для XML).
⚠️ Внимание: При работе с ХранилищеЗначения учитывайте, что его содержимое может быть сжато или зашифровано. Прямая замена строк в таких полях без предварительной распаковки приведёт к повреждению данных.

7. Типичные ошибки и как их избежать

Даже опытные разработчики допускают ошибки при замене строк. Вот самые распространённые ловушки:

  1. Зацикливание при рекурсивной замене

    Если заменяемая подстрока является частью строки замены, возникнет бесконечный цикл. Например:

    СТРЗАМЕНИТЬ("абв", "а", "аб") → "аббв" (ожидалось "аббв", но на следующей итерации "б" тоже заменится)

    Решение: используйте временные переменные или проверяйте результат на каждом шаге.

  2. Игнорирование NULL-значений

    Функции вроде СТРЗАМЕНИТЬ() вернут NULL, если на входе NULL. Всегда добавляйте проверку:

    ВЫБРАТЬ
    

    ВЫРАЗИТЬ(СТРЗАМЕНИТЬ(ЕСТЬNULL(Поле, ""), "а", "б") КАК Строка)

  3. Проблемы с кодировками

    При работе с данными из внешних источников (например, XML или JSON) символы могут отображаться как "кракозябры". Используйте СтрокаВДвоичныеДанные() с указанием кодировки:

    Текст = СтрокаИзДвоичныхДанных(ДвоичныеДанные, КодировкаТекста.UTF8);
💡

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

FAQ: Частые вопросы по замене строк в 1С

Можно ли в одном запросе сделать несколько замен подряд?

Да, но синтаксис будет громоздким. Лучше использовать вложенные функции:

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

СТРЗАМЕНИТЬ(Поле, "а", "б"),

"в", "г"

)

Для более 3-4 замен целесообразнее использовать временные таблицы или обработку в коде.

Как заменить строку с учётом регистра?

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

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

НРСТР(Поле, "Абв"),

НРСТР("аБВ", "абв"),

"НовоеЗначение"

)

Или используйте регулярные выражения с флагом "i" (нечувствительность к регистру).

Почему после замены в запросе данные в базе не изменились?

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

  1. Конструкцию ОБНОВИТЬ (если замена простая и не требует сложной логики).
  2. Обработку результата запроса в коде с последующей записью объектов.
  3. Временные таблицы с последующим переносом данных.

Пример с ОБНОВИТЬ:

ОБНОВИТЬ Справочник.Номенклатура

УСТАНОВИТЬ Наименование = СТРЗАМЕНИТЬ(Наименование, "стар.", "нов.")

ГДЕ НАЙТИ(Наименование, "стар.") > 0;

Как заменить строку в запросе к внешней базе (PostgreSQL, MS SQL)?

При работе с внешними СУБД через 1С:Предприятие используйте native-функции SQL:

  • 🐘 PostgreSQL: REPLACE() или REGEXP_REPLACE().
  • 🖥️ MS SQL: REPLACE() или STUFF() + CHARINDEX().
  • 🐘 Oracle: REGEXP_REPLACE() или REPLACE().

Пример для MS SQL:

ВЫБРАТЬ

ВнешняяБаза.Поле КАК Оригинал,

ВНЕШНЯЯФУНКЦИЯ("REPLACE", ВнешняяБаза.Поле, "а", "б") КАК Результат

ИЗ

ВнешнийИсточник.Таблица КАК ВнешняяБаза

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

Как отменить замену, если что-то пошло не так?

1С:Предприятие не поддерживает откат (ROLLBACK) для операций, выполненных через запросы с ОБНОВИТЬ или УДАЛИТЬ. Чтобы обезопасить себя:

  1. Всегда делайте резервную копию базы перед массовыми заменами.
  2. Используйте НачатьТранзакцию() и ОтменитьТранзакцию() при обработке в коде.
  3. Для критичных операций пишите логи изменений в отдельную таблицу:
// Пример логирования изменений

ПередЗаменой = Объект.Наименование;

Объект.Наименование = НовоеНаименование;

ЗаписатьЛогИзменений(Объект.Ссылка, "Наименование", ПередЗаменой, НовоеНаименование);