Разработка и Конфигурация · 13 мин
Как убрать лидирующие нули в запросе 1С
Как убрать лидирующие нули в запросе 1С: приведение к числу, ПОДСТРОКА, соединение с таблицей цифр. Примеры кода, ограничения способов и типичные ошибки.
Лидирующие нули встречаются в номерах документов, кодах справочников, артикулах и штрихкодах почти в любой конфигурации 1С. Они нужны для сортировки и уникальности, но при выгрузке во внешние системы, сопоставлении данных из разных баз или формировании отчётов нули мешают: строка «0000000123» не равна строке «123», и соединения таблиц в запросе перестают работать.
В языке запросов 1С нет встроенной функции, которая напрямую обрезает нули слева, поэтому задачу решают обходными путями. Существует три рабочих подхода: приведение строки к числу через ВЫРАЗИТЬ, итеративное удаление нулей через ПОДСТРОКА и сравнение с нулём, а также соединение с заранее подготовленной таблицей чисел. Выбор зависит от состава данных: чисто числовые строки обрабатываются одним способом, смешанные (с буквами и префиксами) — другим.
Ниже разобраны все три подхода с готовыми фрагментами кода, их ограничения, способы проверки результата и типичные ошибки, которые приводят к потере данных или падению запроса.
Как определить, какой способ подойдёт под ваши данные
Прежде чем писать запрос, посмотрите на реальное содержимое поля. Откройте несколько типичных записей и ответьте на два вопроса: состоит ли строка только из цифр и есть ли в ней значимые нули, которые нельзя терять. Например, в номере документа «0000-001234» нули после префикса лидирующие, а в артикуле «001200» последние два нуля могут быть значимой частью кода.
Второй момент — длина числа. Приведение к ЧИСЛО имеет ограничение по разрядности (максимум 38 знаков, а на практике разумно ограничиваться 15–20), поэтому длинные коды из 25–30 символов числовым способом не обработать. Третий фактор — где будет использоваться результат: если он нужен только для соединения таблиц внутри запроса, достаточно привести обе стороны к одному виду, и иногда проще не убирать нули, а наоборот, дополнить короткую строку нулями.
Как выбрать действие
Способ 1: приведение к числу через ВЫРАЗИТЬ
Самый компактный приём для чисто цифровых строк — привести поле к числу. Числовое представление не хранит лидирующих нулей, поэтому «000123» превращается в 123. Если дальше нужна строка, результат приводят обратно через ВЫРАЗИТЬ к типу СТРОКА или оставляют числом, если поле используется только для соединения.
ВЫБРАТЬ
ВЫРАЗИТЬ(Номенклатура.Код КАК ЧИСЛО(10, 0)) КАК КодБезНулей
ИЗ
Справочник.Номенклатура КАК Номенклатура
У способа есть жёсткое ограничение: если в поле встретится хотя одна строка с нечисловыми символами (буква, дефис, пробел), запрос завершится с ошибкой преобразования. Поэтому перед использованием проверьте данные запросом, который ищет нецифровые значения, например через ПОДСТРОКА и сравнение каждого символа, либо вложенным запросом с условием на длину и состав.
Ещё одна ловушка — пробелы. Строка « 000123» с пробелом слева в ряде случаев преобразуется корректно, но с неразрывными пробелами или табуляцией из импортированных данных — нет. Если данные приходят из внешних файлов, сначала очистите их средствами встроенного языка (СокрЛП, СтрЗаменить) и только потом обрабатывайте запросом.
Способ 2: цепочка ВЫБОР и ПОДСТРОКА для смешанных строк
Когда в строке могут быть буквы и префиксы, а нули нужно срезать только слева, применяют конструкцию ВЫБОР, которая последовательно проверяет первый символ. Идея проста: если первый символ — «0», берём подстроку со второго символа; если и там ноль — ещё глубже, и так на нужную глубину.
ВЫБРАТЬ
ВЫБОР
КОГДА ПОДСТРОКА(Т.Код, 1, 1) = "0"
ТОГДА ВЫБОР
КОГДА ПОДСТРОКА(Т.Код, 2, 1) = "0"
ТОГДА ПОДСТРОКА(Т.Код, 3, 100)
ИНАЧЕ ПОДСТРОКА(Т.Код, 2, 100)
КОНЕЦ
ИНАЧЕ Т.Код
КОНЕЦ КАК КодБезНулей
ИЗ
Справочник.Номенклатура КАК Т
Глубина вложенности должна покрывать максимально возможное количество нулей. Если коды фиксированной длины 11 символов, а значимая часть начинается не раньше третьего знака, достаточно двух-трёх уровней. Для произвольных данных цепочка разрастается, и здесь разумнее вынести обработку во встроенный язык.
Обратите внимание: второй параметр ПОДСТРОКА — это позиция начала (нумерация с единицы), а третий — длина. Указание заведомо большой длины (например, 100) безопасно: функция вернёт строку до конца. Ошибка новичков — перепутать второй и третий параметры и получить обрезанные значения.
Способ 3: обработка результата во встроенном языке
Часто честнее признать: язык запросов не предназначен для посимвольной обработки строк, и перенести задачу на уровень встроенного языка проще и надёжнее. Запрос выбирает исходные значения, а обход выборки удаляет нули циклом.
Пока Выборка.Следующий() Цикл
Код = Выборка.Код;
Пока СтрДлина(Код) > 1 И Лев(Код, 1) = "0" Цикл
Код = Сред(Код, 2);
КонецЦикла;
КонецЦикла;
Условие СтрДлина(Код) > 1 защищает от вырожденного случая: строка «0» или «000» должна превратиться в «0», а не в пустую строку. Если пустое значение допустимо, условие можно упростить до СтрДлина(Код) > 0, но тогда в дальнейших сравнениях пустая строка и «0» перестанут совпадать — учитывайте это в логике обработки.
Этот вариант особенно удобен, когда результат запроса и так обходится в коде: при формировании файла обмена, заполнении табличного документа или передаче данных через HTTP-сервис. Дополнительный проход по данным почти не влияет на производительность по сравнению с громоздким запросом.
- 1Проверьте состав поля: только цифры или смешанные символы, есть ли пробелы
- 2Для чисто цифровых полей примените ВЫРАЗИТЬ(Поле КАК ЧИСЛО(15,0))
- 3Для смешанных строк постройте цепочку ВЫБОР с ПОДСТРОКА на глубину максимального числа нулей
- 4Если результат обходится в коде — удалите нули циклом Пока с Лев() и Сред()
- 5Проверьте результат на контрольных значениях: «000123» → «123», «0» → «0», «А0012» → обрабатывается без ошибки
Как убрать нули при соединении таблиц
На практике чаще всего задача возникает не сама по себе, а при сопоставлении данных из двух источников: в одной базе номер хранится как «000456», в другой — как «456». Прямое соединение по равенству строк ничего не найдёт. Здесь есть две стратегии: обрезать нули у длинной строки или дополнить нулями короткую.
Дополнение нулями слева часто надёжнее обрезки, потому что не требует анализа состава строки. Если известна целевая длина (например, 11 знаков), короткую строку дополняют конкатенацией: сначала приклеивают слева максимально возможное количество нулей, затем берут нужное количество символов справа через ПОДСТРОКА с вычисляемой позицией либо во встроенном языке через Формат с форматной строкой «ЧЦ=11; ЧВН=; ЧГ=» для чисел.
Если всё же нужно обрезать, применяйте к обеим сторонам соединения одинаковое преобразование и убедитесь, что оно детерминировано: одинаковая строка на входе должна давать одинаковый результат. Соединение по вычисляемому выражению с ВЫБОР работает, но на больших таблицах может замедлить запрос, так как СУБД не всегда сможет использовать индексы. Для массовых обменов рассмотрите вариант: заранее записать нормализованное значение в отдельный реквизит и соединяться по нему.
Сравнение вариантов
Самый короткий код, но падает на любых нечисловых символах и ограничен разрядностью числа
Работает с любыми строками, но глубина вложенности фиксирована и код быстро разрастается
Максимально гибкий вариант, подходит для любых данных, но требует обхода выборки в коде
Альтернатива обрезке при соединении таблиц: не требует анализа состава строки, но нужно знать целевую длину
Проверка результата и контрольные значения
После внедрения любого из способов прогоните запрос на контрольном наборе. Минимальный набор случаев: обычное значение с нулями («000123» → «123»), значение без нулей («456» → «456»), строка из одних нулей («000» → «0» или пустая строка — зафиксируйте ожидаемое поведение), значение с буквами («А007»), значение с пробелами по краям и максимально длинное значение из реальных данных.
Полезный приём — вывести в одном запросе исходное и преобразованное поле рядом и отсортировать по длине исходного значения по убыванию: так в начало списка попадут самые «тяжёлые» случаи с максимальным числом нулей. Дополнительно постройте проверочный запрос, который ищет записи, где преобразованное значение всё ещё начинается с «0» и при этом длиннее одного символа — это прямой индикатор недостаточной глубины обработки.
Как проверить результат
Получено «123»
Остались нули слева или значение обрезано справа
Превращена в «0» или пустую строку по принятому правилу
Запрос упал с ошибкой или вернул NULL без причины
Обработана без ошибки по выбранному правилу
Ошибка преобразования типов остановила запрос
Количество совпадений соответствует ожиданиям на контрольном примере
Соединение пустое или дублирует строки
Типичные ошибки и ограничения
Самая частая ошибка — применение ВЫРАЗИТЬ к числу без проверки данных. В тестовой базе всё работает, а в рабочей находится одна запись с префиксом, и запрос падает в регламентном задании в три часа ночи. Вторая типичная проблема — недостаточная глубина цепочки ВЫБОР: разработчик закладывает три уровня, а в данных встречается шесть нулей.
Третья группа ошибок связана с потерей значимых символов. В некоторых учётных системах нули внутри кода значимы: «010203» после обрезки лидирующих нулей должно остаться «10203», но если случайно применить СтрЗаменить(Код, "0", ""), удалятся все нули, включая значимые. Удалять нужно только нули слева, последовательно, пока первый символ равен нулю.
Наконец, помните про производительность. Выражения с ВЫБОР и ПОДСТРОКА в условиях соединения и отборах блокируют использование индексов. На таблицах в сотни тысяч записей такой запрос может выполняться в десятки раз дольше. Для регулярных операций нормализуйте данные один раз и храните готовое значение.
Частые вопросы
Можно ли убрать лидирующие нули у номера документа, не меняя сам номер?
Да, если обработка выполняется только на этапе вывода: в запросе, в макете печатной формы или при формировании строки представления. Сам номер в базе при этом не изменяется. Менять хранимый номер не рекомендуется — это нарушит нумерацию и может привести к конфликтам при обмене данными.
Почему ВЫРАЗИТЬ(Поле КАК ЧИСЛО) возвращает ошибку, хотя все значения выглядят числовыми?
Чаще всего в данных скрыты непечатаемые символы: неразрывные пробелы, табуляции, переносы строк из импортированных файлов. Визуально они не видны. Проверьте данные запросом на длину строки и наличие символов, отличных от цифр, и очистите значения через СокрЛП и СтрЗаменить перед преобразованием.
Как убрать нули только из числовой части кода с префиксом, например «АБ-000123»?
Универсальной функции в языке запросов для этого нет. Практичный путь — обработать строку во встроенном языке: отделить префикс по известному разделителю, обрезать нули у числовой части циклом, затем собрать строку обратно. Если префикс фиксированной длины, часть операций можно выполнить и в запросе через ПОДСТРОКА.
Что лучше для соединения двух баз: обрезать нули или дополнять ими?
Дополнение нулями до фиксированной длины обычно надёжнее: оно не требует анализа состава строки и не падает на нечисловых значениях. Обрезка оправдана, когда внешняя система принимает значения только без нулей и длина результата не важна.
Влияет ли удаление нулей в запросе на производительность?
В секции ВЫБРАТЬ влияние невелико даже на крупных таблицах. Заметные тормоза возникают, когда выражение с ПОДСТРОКА или ВЫРАЗИТЬ стоит в условии соединения или отбора: СУБД не может использовать индекс по вычисляемому значению. В таких случаях нормализованное значение лучше хранить в отдельном реквизите.
Как обработать строку «000», чтобы не получить пустое значение?
Добавьте защитное условие: обрезайте нули только пока длина строки больше одного символа. В цепочке ВЫБОР это дополнительная проверка на каждом уровне, во встроенном языке — условие СтрДлина(Код) > 1 в заголовке цикла. Тогда «000» корректно превратится в «0».
Что важно запомнить
Для чисто цифровых строк лидирующие нули убирают через ВЫРАЗИТЬ к ЧИСЛО, для смешанных — цепочкой ВЫБОР с ПОДСТРОКА или обработкой во встроенном языке. Перед числовым преобразованием обязательно проверяйте данные на нечисловые символы, закладывайте глубину обрезки с запасом и защищайте строку из одних нулей от превращения в пустое значение.