Разработка и Конфигурация · 11 мин
Как разделить строку в запросе 1С
Как разделить строку в запросе 1С: ПОДСТРОКА, СтрРазделить, соединение с таблицей чисел, обработка ФИО и составных полей. Примеры кода и типичные ошибки.
Задача разделить строку в запросе 1С возникает регулярно: нужно извлечь фамилию из поля «Иванов Иван Иванович», вытащить артикул из составного кода, разобрать адрес на части или отобрать записи по фрагменту строки. Сложность в том, что язык запросов 1С не содержит функции, аналогичной СтрРазделить из встроенного языка, — прямого способа разбить строку по разделителю на массив подстрок в запросе нет.
Тем не менее задача решается несколькими обходными путями: функциями ПОДСТРОКА и связанными приёмами, предварительной подготовкой данных во временных таблицах, соединением со служебной таблицей чисел либо переносом логики на уровень встроенного языка, где доступна СтрРазделить. Выбор зависит от того, известна ли позиция разделителя, сколько частей нужно получить и где будет использоваться результат.
Ниже разобраны рабочие приёмы с примерами кода, ограничения каждого подхода и критерии выбора. Материал ориентирован на разработчиков и внедренцев, работающих с управляемыми приложениями и современными версиями платформы.
Почему в запросе 1С нельзя просто вызвать СтрРазделить
Язык запросов 1С — декларативный: он описывает, какие данные нужны, а не как их обрабатывать по шагам. В нём доступны строковые функции ПОДСТРОКА, ДЛИНАСТРОКИ (в виде функции ДЛСТРОКИ в некоторых диалектах — чаще используется вычисление через ПОДСТРОКА и сравнения), оператор ПОДОБНО и сцепление строк. Функции, возвращающей массив или таблицу подстрок, среди них нет, потому что результат запроса — всегда плоская таблица, а не коллекция переменной длины.
Из этого следуют два практических вывода. Первый: если нужно просто отрезать часть строки по известным позициям — задача решается внутри запроса функцией ПОДСТРОКА. Второй: если строку нужно разбить на неизвестное заранее количество частей и каждую часть получить отдельной строкой результата — потребуется либо хитрость с соединениями, либо подготовка данных до выполнения основного запроса.
Разделение строки функцией ПОДСТРОКА при известной позиции разделителя
Самый простой сценарий — разделитель всегда стоит на фиксированной позиции или границы частей известны из формата данных. Например, код вида «ABC-12345», где первые три символа — префикс, а остальное — номер. Тогда запрос выглядит так:
ВЫБРАТЬ
ПОДСТРОКА(Товары.Код, 1, 3) КАК Префикс,
ПОДСТРОКА(Товары.Код, 5, 100) КАК Номер
ИЗ
Справочник.Товары КАК Товары
Третий параметр можно заведомо завысить (например, 100 или 1000): лишние символы не вернутся, функция обрежет результат по фактической длине строки. Это удобно, когда точная длина «хвоста» неизвестна.
Проверка результата проста: сцепите полученные части обратно с разделителем и сравните с исходной строкой. Если сцепка совпадает, разделение корректно.
Разделение по переменной позиции разделителя через таблицу чисел
Когда позиция разделителя заранее неизвестна (типичный случай — ФИО «Иванов Иван Иванович» с пробелами в разных местах), применяют приём со служебной таблицей чисел. Идея: соединить таблицу с набором чисел 1, 2, 3… и для каждой позиции проверить, является ли символ разделителем.
Таблицу чисел можно получить из любого достаточно длинного набора данных или сформировать явно:
ВЫБРАТЬ 1 КАК Н
ПОМЕСТИТЬ Числа
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 3
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 4
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 5
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 6
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 7
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 8
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 9
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 10
;
ВЫБРАТЬ
Сотрудники.ФИО КАК ФИО,
Числа.Н КАК Позиция
ПОМЕСТИТЬ Позиции
ИЗ
Справочник.Сотрудники КАК Сотрудники
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Числа КАК Числа
ПО (ПОДСТРОКА(Сотрудники.ФИО, Числа.Н, 1) = " ")
Дальше из таблицы «Позиции» берут минимальную позицию пробела (конец фамилии) и максимальную (начало отчества), и через ПОДСТРОКА вырезают нужные части. Приём работает, но порождает декартово произведение: на каждую строку — до десятка соединений. На больших таблицах это заметно замедляет запрос.
Разделение строки через СтрРазделить и временную таблицу
Самый гибкий и производительный путь — разбить строку до запроса, во встроенном языке, и передать результат в запрос как временную таблицу. Метод СтрРазделить(Строка, Разделитель) возвращает массив подстрок, который легко превратить в таблицу значений:
ТаблицаЧастей = Новый ТаблицаЗначений;
ТаблицаЧастей.Колонки.Добавить("НомерЧасти", Новый ОписаниеТипов("Число"));
ТаблицаЧастей.Колонки.Добавить("Значение", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(150)));
МассивЧастей = СтрРазделить(ИсходнаяСтрока, ",");
Номер = 0;
Для Каждого Часть Из МассивЧастей Цикл
Номер = Номер + 1;
НоваяСтрока = ТаблицаЧастей.Добавить();
НоваяСтрока.НомерЧасти = Номер;
НоваяСтрока.Значение = СокрЛП(Часть);
КонецЦикла;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст =
"ВЫБРАТЬ
| Т.НомерЧасти КАК НомерЧасти,
| Т.Значение КАК Значение
|ПОМЕСТИТЬ ЧастиСтроки
|ИЗ
| &ТаблицаЧастей КАК Т";
Запрос.УстановитьПараметр("ТаблицаЧастей", ТаблицаЧастей);
Запрос.Выполнить();
Дальше временная таблица «ЧастиСтроки» соединяется с любыми данными: например, можно найти товары, чьи артикулы перечислены в строке через запятую. Это стандартный приём для обработки списков, введённых пользователем одной строкой.
- 1Определите, известна ли позиция разделителя и сколько частей нужно получить
- 2При фиксированной позиции используйте ПОДСТРОКА прямо в запросе
- 3При переменной позиции на небольших данных примените соединение с таблицей чисел
- 4При сложной логике или больших объёмах разбейте строку через СтрРазделить и передайте результат временной таблицей
- 5Проверьте результат на строках с краевыми случаями: пустая строка, разделитель в начале и в конце, несколько разделителей подряд
Разбор ФИО и адресов: практические сценарии
Извлечение фамилии из полного ФИО
Фамилия — это всё до первого пробела. Если объём данных невелик, позицию первого пробела находят соединением с таблицей чисел и агрегатом МИНИМУМ, затем применяют ПОДСТРОКА(ФИО, 1, ПозицияПробела - 1). Имя и отчество получают аналогично через максимальную позицию пробела.
Надёжнее делать это при записи данных: при сохранении сотрудника разбивать ФИО методом СтрРазделить и складывать фамилию, имя и отчество в отдельные реквизиты. Тогда запросы остаются тривиальными, а сортировка и поиск по фамилии работают быстро и с использованием индексов.
Список значений одной строкой
Пользователи часто вводят несколько артикулов или номеров через запятую в одно поле отбора. Правильная обработка: СтрРазделить по запятой, СокрЛП каждого элемента, удаление пустых значений, передача массива в параметр запроса и условие В (&СписокАртикулов). Разбивать такую строку средствами самого запроса не нужно — встроенный язык справляется лучше.
Сравнение вариантов
Подходит при известной позиции разделителя и фиксированном формате. Ограничение: не ищет разделитель сама.
Позволяет найти позицию разделителя внутри запроса. Ограничение: тяжёлый запрос на больших таблицах, сложная поддержка.
Универсальный и быстрый вариант для любой логики. Ограничение: требует кода во встроенном языке, не работает в «чистом» запросе консоли.
Лучший вариант для повторяющихся выборок. Ограничение: нужно менять структуру данных и логику записи.
Частые ошибки и ограничения
Первая типичная ошибка — забыть, что позиции в ПОДСТРОКА считаются с единицы, а не с нуля. Смещение на один символ даёт обрезанные или сдвинутые значения, которые легко пропустить на тестовых данных.
Вторая ошибка — не учесть строки без разделителя. Если в поле нет пробела или запятой, соединение с таблицей чисел просто не вернёт строку, и запись «потеряется» из результата. Добавляйте обработку: если позиция разделителя не найдена, считать всю строку первой частью. Во встроенном языке СтрРазделить в этом случае вернёт массив из одного элемента — это поведение предсказуемо и безопасно.
Третья ошибка — лишние пробелы вокруг частей. После разделения по запятой элемент « 123 » не сравнится со строкой «123». Всегда применяйте СокрЛП к каждой части до передачи в запрос.
Отдельно отметим ограничение по длине: при передаче таблицы значений параметром колонки должны иметь явно заданные типы и достаточную длину строки, иначе значения могут обрезаться под длину первого переданного значения.
Как проверить корректность разделения
После реализации проверьте результат на контрольном наборе: обычная строка, строка без разделителя, строка, начинающаяся и заканчивающаяся разделителем, строка из одних разделителей, пустая строка. Все случаи должны давать осмысленный результат без ошибок исполнения.
Полезный приём — контрольная сцепка: соберите части обратно через разделитель и сравните с исходной строкой. Расхождение указывает на потерю данных при разделении. В отладчике удобно смотреть содержимое массива после СтрРазделить и временной таблицы после передачи в запрос.
Как проверить результат
Возвращается как одна часть целиком
Запись исчезает из результата
Появляется пустая часть, логика её обрабатывает
Ошибка исполнения или сдвиг значений
Части очищены через СокрЛП и сравниваются корректно
Соединения по значению не находят совпадений
Совпадает с исходной строкой
Есть расхождения — данные теряются
Что важно запомнить
Прямой функции разделения строки в языке запросов 1С нет. При известной позиции используйте ПОДСТРОКА, при переменной — соединение с таблицей чисел на небольших данных, а универсальное решение — СтрРазделить во встроенном языке с передачей результата временной таблицей. Для регулярных выборок храните части строки в отдельных реквизитах.
Частые вопросы
Можно ли разделить строку прямо в консоли запросов без кода?
Только частично: функцией ПОДСТРОКА при известных позициях или через соединение с таблицей чисел для поиска разделителя. Полноценный разбор на произвольное число частей без встроенного языка невозможен.
Как разбить строку на отдельные символы в запросе?
Через соединение с таблицей чисел: ПОДСТРОКА(Строка, Н, 1) вернёт символ на позиции Н. Количество чисел в служебной таблице должно покрывать максимальную длину строки.
Что вернёт СтрРазделить для пустой строки?
Массив из одного пустого элемента. Это стоит учитывать при подсчёте частей: проверяйте не только количество элементов, но и их содержимое.
Как разделить строку по нескольким разделителям сразу?
Во встроенном языке перед СтрРазделить замените все дополнительные разделители на основной функцией СтрЗаменить, затем разбивайте по одному разделителю. В запросе такой приём недоступен.
Влияет ли разделение строки на производительность запроса?
ПОДСТРОКА с константными позициями почти не влияет. Соединение с таблицей чисел кратно увеличивает объём обработки и на больших таблицах ощутимо замедляет выполнение — в таких случаях переносите разделение во временную таблицу.
Как найти позицию первого вхождения подстроки в запросе?
Отдельной функции поиска позиции нет. Используют соединение с таблицей чисел с условием ПОДСТРОКА(Строка, Н, ДлинаПодстроки) = Подстрока и агрегат МИНИМУМ по Н, либо оператор ПОДОБНО, если достаточно проверки факта вхождения без позиции.