Замена строк в запросах 1С:Предприятие 8.3 — одна из самых частых задач при работе с базой данных.hether вы исправляете опечатки в справочниках, унифицируете форматы данных или очищаете поля от лишних символов, умение правильно модифицировать строки сэкономит часы рутинной работы. Но стандартные функции вроде СТРЗАМЕНИТЬ() часто используют неэффективно, а про регулярные выражения в контексте запросов многие даже не задумываются.
В этой статье разберём 5 практических способов замены строк — от базовых до продвинутых, с учётом особенностей синтаксиса 1С и ограничений платформы. Вы узнаете, как обойти типичные ошибки (например, с многобайтовыми кодировками), когда лучше использовать ПОДСТРОКА() вместо НАЙТИ(), и почему иногда проще сделать замену не в запросе, а на уровне кода. Все примеры протестированы на актуальных релизах платформы и адаптированы для реальных бизнес-задач.
1. Базовая замена: функция СТРЗАМЕНИТЬ()
Самый простой и распространённый способ — встроенная функция СТРЗАМЕНИТЬ(). Она работает по принципу "найти и заменить" и поддерживает неограниченное количество вхождений. Синтаксис:
СТРЗАМЕНИТЬ(ИсходнаяСтрока, ПодстрокаДляПоиска, ПодстрокаДляЗамены)
Пример использования в запросе:
ВЫБРАТЬ
СТРЗАМЕНИТЬ(Номенклатура.Наименование, "ООО", "ИП") КАК ИсправленноеНаименование
ИЗ
Справочник.Номенклатура КАК Номенклатура
Важные нюансы:
- 🔹 Регистрозависимость: функция различает заглавные и строчные буквы. Чтобы игнорировать регистр, предварительно преобразуйте строку с помощью
НРСТР()(нерегистрочувствительный поиск). - 🔹 Пустые строки: если
ПодстрокаДляПоискапустая, функция вернёт исходную строку без изменений. - 🔹 Производительность: при замене в больших полях (например,
Комментарийдлиной 1000+ символов) лучше использоватьПОДСТРОКА()сНАЙТИ()для оптимизации.
⚠️ Внимание: В версиях платформы ниже 8.3.14 функция СТРЗАМЕНИТЬ() могла неправильно обрабатывать символы юникода (например, кириллицу в UTF-8). Если работаете со старыми базами, тестируйте результат на реальных данных.
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 и ниже) регулярные выражения работают только во встроенном языке, но не в запросах.
⚠️ Внимание: Регулярные выражения в запросах 1С могут значительно замедлить выполнение при обработке больших таблиц (100К+ строк). Для таких случаев лучше использовать временные таблицы или обрабатывать данные порциями.
4. Замена с использованием временных таблиц
Если замена строк требует сложной логики (например, зависит от данных из других таблиц), оптимальное решение — временные таблицы. Они позволяют разделить обработку на этапы и избежать громоздких вложенных функций.
Пример: заменить сокращения в наименованиях номенклатуры на полные названия из справочника:
// 1. Создаём временную таблицу с правилами замены
ВЫБРАТЬ
Сокращения.Сокращение КАК ЧтоИскать,
Сокращения.ПолноеНазвание КАК НаЧтоМенять
ПОМЕСТИТЬ ВТ_ПравилаЗамены
ИЗ
Справочник.Сокращения КАК Сокращения;
// 2. Применяем замену с JOIN'ом
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка,
СТРЗАМЕНИТЬ(
Номенклатура.Наименование,
ВТ_ПравилаЗамены.ЧтоИскать,
ВТ_ПравилаЗамены.НаЧтоМенять
) КАК ИсправленноеНаименование
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ПравилаЗамены КАК ВТ_ПравилаЗамены
ПО НЕ (НАЙТИ(Номенклатура.Наименование, ВТ_ПравилаЗамены.ЧтоИскать) = 0)
Преимущества подхода:
- 🔧 Гибкость: правила замены хранятся отдельно и легко редактируются.
- 📊 Производительность: временные таблицы оптимизированы для больших объёмов данных.
- 🔄 Возможность многоэтапной обработки (например, сначала заменить сокращения, потом очистить пробелы).
Определить все возможные варианты замен|Создать справочник или таблицу с правилами|Протестировать логику на небольшой выборке|Оптимизировать индексы для JOIN'ов-->
5. Замена строк в коде (альтернатива запросам)
Иногда проще и быстрее сделать замену не в запросе, а на уровне встроенного языка 1С. Это актуально для:
- 🔄 Многократных замен в цикле (например, при обработке каждого документа).
- 📝 Сложной логики, зависящей от контекста (например, замена только для определённых видов номенклатуры).
- 💾 Операций с файлами или внешними источниками данных.
Пример на встроенном языке:
Выборка = Запросы.НоменклатураБезЦифр.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ТекущееНаименование = Выборка.Наименование;
// Заменяем все цифры на пустую строку
НовоеНаименование = РегВыражение("[0-9]", "", ТекущееНаименование);
// Обновляем объект
Объект = Выборка.Ссылка.ПолучитьОбъект();
Объект.Наименование = НовоеНаименование;
Объект.Записать();
КонецЦикла;
Когда этот метод предпочтительнее запросов:
| Критерий | Запрос | Код 1С |
|---|---|---|
| Производительность при 10К+ строках | ⚠️ Возможны тормоза | ✅ Быстрее (порционная обработка) |
| Сложная логика замены | ❌ Ограничен функционал | ✅ Полная свобода |
| Транзакционность | ✅ Автоматическая | ⚠️ Нужно управлять вручную |
Как ускорить обработку больших выборок в коде?
Используйте метод ВыбратьПакетом() вместо Выбрать() для порционной загрузки данных (например, по 1000 строк за итерацию). Также отключите автоматическое управление транзакциями с помощью НачатьТранзакцию()/ЗафиксироватьТранзакцию() для крупных пакетов обновлений.
6. Особенности замены в разных типах данных
Поведение функций замены строк может отличаться в зависимости от типа поля, с которым вы работаете. Рассмотрим ключевые нюансы:
6.1. Строковые поля (Наименование, Комментарий)
Для полей типа Строка доступны все описанные методы. Главное ограничение — максимальная длина строки (обычно 255 или 1024 символа в зависимости от конфигурации). При превышении лимита используйте:
- 📜 Поле типа
Строка неограниченной длины(если поддерживается конфигурацией). - 🗄️ Хранение длинного текста в отдельной таблице с ссылкой.
6.2. Поля с перечислениями (ВидНоменклатуры, Статус)
Заменять строки в полях типа Перечисление или СправочникСсылка напрямую нельзя — нужно работать с представлением объекта. Пример:
ВЫБРАТЬ
Документы.Вид КАК ВидДокумента,
СТРЗАМЕНИТЬ(ВЫРАЗИТЬ(Документы.Вид КАК Строка), "Заказ", "Зак.") КАК СокращённоеНазвание
ИЗ
Документ.ЗаказПокупателя КАК Документы
6.3. Бинарные данные и BLOB-поля
Для полей типа ХранилищеЗначения или ДвоичныеДанные стандартные строковые функции не работают. Используйте:
- 🔧
ПолучитьТекстИзДвоичныхДанных()для преобразования в строку. - 🔧 Обработку на уровне кода с использованием COM-объектов (например,
MSXML2.DOMDocumentдля XML).
⚠️ Внимание: При работе с ХранилищеЗначения учитывайте, что его содержимое может быть сжато или зашифровано. Прямая замена строк в таких полях без предварительной распаковки приведёт к повреждению данных.
7. Типичные ошибки и как их избежать
Даже опытные разработчики 1С допускают ошибки при замене строк. Вот самые распространённые ловушки:
- Зацикливание при рекурсивной замене
Если заменяемая подстрока является частью строки замены, возникнет бесконечный цикл. Например:
СТРЗАМЕНИТЬ("абв", "а", "аб") → "аббв" (ожидалось "аббв", но на следующей итерации "б" тоже заменится)Решение: используйте временные переменные или проверяйте результат на каждом шаге.
- Игнорирование NULL-значений
Функции вроде
СТРЗАМЕНИТЬ()вернутNULL, если на входеNULL. Всегда добавляйте проверку:ВЫБРАТЬВЫРАЗИТЬ(СТРЗАМЕНИТЬ(ЕСТЬNULL(Поле, ""), "а", "б") КАК Строка)
- Проблемы с кодировками
При работе с данными из внешних источников (например, XML или JSON) символы могут отображаться как "кракозябры". Используйте
СтрокаВДвоичныеДанные()с указанием кодировки:Текст = СтрокаИзДвоичныхДанных(ДвоичныеДанные, КодировкаТекста.UTF8);
Всегда тестируйте замену на копии базы данных перед применением на рабочей системе. Особенно это критично для полей, участвующих в индексах или используемых в отчётах.
FAQ: Частые вопросы по замене строк в 1С
Можно ли в одном запросе сделать несколько замен подряд?
Да, но синтаксис будет громоздким. Лучше использовать вложенные функции:
СТРЗАМЕНИТЬ(
СТРЗАМЕНИТЬ(Поле, "а", "б"),
"в", "г"
)
Для более 3-4 замен целесообразнее использовать временные таблицы или обработку в коде.
Как заменить строку с учётом регистра?
Функция СТРЗАМЕНИТЬ() чувствительна к регистру. Чтобы игнорировать регистр, преобразуйте строку к нижнему регистру перед заменой:
СТРЗАМЕНИТЬ(
НРСТР(Поле, "Абв"),
НРСТР("аБВ", "абв"),
"НовоеЗначение"
)
Или используйте регулярные выражения с флагом "i" (нечувствительность к регистру).
Почему после замены в запросе данные в базе не изменились?
Запрос в 1С по умолчанию только выбирает данные, но не изменяет их. Чтобы сохранить изменения, используйте:
- Конструкцию
ОБНОВИТЬ(если замена простая и не требует сложной логики). - Обработку результата запроса в коде с последующей записью объектов.
- Временные таблицы с последующим переносом данных.
Пример с ОБНОВИТЬ:
ОБНОВИТЬ Справочник.Номенклатура
УСТАНОВИТЬ Наименование = СТРЗАМЕНИТЬ(Наименование, "стар.", "нов.")
ГДЕ НАЙТИ(Наименование, "стар.") > 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) для операций, выполненных через запросы с ОБНОВИТЬ или УДАЛИТЬ. Чтобы обезопасить себя:
- Всегда делайте резервную копию базы перед массовыми заменами.
- Используйте
НачатьТранзакцию()иОтменитьТранзакцию()при обработке в коде. - Для критичных операций пишите логи изменений в отдельную таблицу:
// Пример логирования изменений
ПередЗаменой = Объект.Наименование;
Объект.Наименование = НовоеНаименование;
ЗаписатьЛогИзменений(Объект.Ссылка, "Наименование", ПередЗаменой, НовоеНаименование);