Разработка и Конфигурация · 11 мин
Преобразование текста в число в запросе 1С
Как в запросе 1С преобразовать строку в число: функция ВЫРАЗИТЬ как число, ограничения, работа с разделителями, проверка результата и типичные ошибки.
В языке запросов 1С нет прямой функции приведения строки к числу вроде Число(), которая есть во встроенном языке платформы. Из-за этого задача «текст как число» в запросе регулярно ставит в тупик: поле хранится как строка, а сортировать, суммировать или сравнивать его нужно как числовое значение. Ситуация типична для данных, загруженных из Excel, веб-сервисов или внешних систем, где числовые реквизиты оказались строковыми.
Основной рабочий инструмент — функция ВЫРАЗИТЬ(... КАК ЧИСЛО(...)). Однако у неё есть важное ограничение: она корректно работает только со строками, содержащими «чистое» числовое представление, и ведёт себя по-разному в зависимости от содержимого. Понимание этих нюансов избавляет от неожиданных NULL в итоговой выборке и ошибок сортировки.
Ниже разобраны способы преобразования строки в число прямо в запросе, обходные приёмы для «грязных» данных (пробелы, неразрывные пробелы, запятые вместо точек), проверка результата и типичные ошибки, которые приводят к потере данных или падению производительности.
Базовый способ: функция ВЫРАЗИТЬ как число
Функция ВЫРАЗИТЬ приводит значение к указанному типу. Для преобразования строки в число синтаксис выглядит так:
ВЫБРАТЬ
ВЫРАЗИТЬ(Данные.КодСтрокой КАК ЧИСЛО(10, 0)) КАК КодЧислом
ИЗ
РегистрСведений.ВнешниеКоды КАК Данные
Параметры типа ЧИСЛО(Длина, Точность) задают максимальную длину числа и количество знаков после запятой. Если реальное значение не помещается в указанную разрядность, запрос может вернуть ошибку или обрезанное значение — зависит от СУБД. Поэтому длину лучше задавать с запасом: ЧИСЛО(15, 2) подходит для большинства учётных величин.
Важно понимать: ВЫРАЗИТЬ — это не «умный» парсер. Она ожидает, что строка уже содержит корректное числовое представление с точкой в качестве разделителя дробной части и без посторонних символов. Строка "123.45" преобразуется успешно, а вот "123,45" или "1 234.5" — с высокой вероятностью дадут NULL.
Почему результат преобразования равен NULL
NULL вместо числа — самый частый симптом при таком преобразовании. Причины обычно следующие:
- в строке есть неразрывные пробелы (частый подарок из Excel и веб-страниц);
- дробная часть отделена запятой, а не точкой;
- встречаются буквы, валютные символы, единицы измерения («100 кг»);
- строка пустая или содержит только пробелы;
- используются разделители разрядов: «1 000 000».
Диагностика проста: выберите исходное строковое поле и результат преобразования рядом, отсортируйте по результату и посмотрите, какие значения «выпали» в NULL. Для проверки на нечисловые строки удобен оператор ПОДОБНО:
ВЫБРАТЬ
Данные.ЗначениеСтрокой
ИЗ
РегистрСведений.Данные КАК Данные
ГДЕ
НЕ Данные.ЗначениеСтрокой ПОДОБНО "[0-9]%"
Шаблон ПОДОБНО в запросах 1С ограничен (нет полноценных регулярных выражений), но для выявления строк, начинающихся не с цифры, его достаточно.
Проверить пробелы, запятые, посторонние символы
Увеличить параметры типа
Применить ВЫРАЗИТЬ к числу в УПОРЯДОЧИТЬ ПО
Сузить выборку, найти выбивающиеся значения
Очистка «грязных» строк прямо в запросе
Если исходные данные содержат неразрывные пробелы или разделители разрядов, их можно убрать вложенными вызовами ПОДСТРОКА — но это громоздко. Практичнее заменить символы заранее. В чистом запросе доступна функция ПОДСТРОКА, но функции замены подстроки в языке запросов нет. Поэтому рабочие варианты такие:
Замена запятой на точку
Трюк с конкатенацией и ПОДСТРОКА помогает только для простых случаев. Надёжнее привести данные к одному формату ещё на этапе загрузки — во встроенном языке функцией СтрЗаменить до записи в базу.
Удаление пробелов
Обычные пробелы по краям убирает приведение типа автоматически в большинстве случаев, но неразрывный пробел (символ 160) — нет. Если данные грузятся извне, лучшая практика — при загрузке выполнить СтрЗаменить(Значение, Символ(160), "") и записывать уже очищенное значение.
Промежуточная таблица с обработкой
Когда очистку нельзя выполнить на этапе загрузки, используют временную таблицу: сначала выбирают строки, потом обрабатывают их кодом на встроенном языке (через таблицу значений с колонкой числового типа), а результат передают обратно в запрос параметром. Это стандартный приём для сложных парсингов.
- 1Выберите исходные строки и найдите значения, дающие NULL после ВЫРАЗИТЬ
- 2Определите мешающие символы: неразрывный пробел, запятая, единицы измерения
- 3Очистите данные на встроенном языке: СтрЗаменить, СокрЛП, затем Число()
- 4Поместите очищенные значения во временную таблицу и передайте в запрос
- 5Соедините временную таблицу с основной выборкой и работайте уже с числами
Сортировка и сравнение строк как чисел
Частая задача — упорядочить строковый код или номер как число. Без преобразования сортировка идёт лексикографически: «1», «10», «2», «25». Решение — применить ВЫРАЗИТЬ прямо в секции УПОРЯДОЧИТЬ ПО:
ВЫБРАТЬ
Номенклатура.Артикул
ИЗ
Справочник.Номенклатура КАК Номенклатура
УПОРЯДОЧИТЬ ПО
ВЫРАЗИТЬ(Номенклатура.Артикул КАК ЧИСЛО(10, 0))
Тот же приём работает в условиях сравнения: ГДЕ ВЫРАЗИТЬ(Поле КАК ЧИСЛО(10, 0)) > 100. Но здесь есть подводный камень: преобразование в условии отключает использование индекса по этому полю, и на больших таблицах запрос заметно замедлится. Если такие сравнения нужны постоянно, правильнее добавить в объект отдельный числовой реквизит и заполнять его при записи.
Альтернативы и смежные приёмы
Если ВЫРАЗИТЬ не справляется, есть несколько обходных путей. Выбор зависит от того, где возникает задача и насколько «грязные» данные.
Первый вариант — обработка на встроенном языке: функция Число() умеет больше, чем приведение в запросе, а в связке со СтрЗаменить и ОписаниеТипов позволяет безопасно распарсить почти любой формат. Результат передаётся в запрос через временную таблицу или параметр.
Второй вариант — вычисляемое поле в СКД или выражение в запросе с конструкцией ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ 0 КОНЕЦ, чтобы заменить NULL на ноль и не ломать итоги:
ВЫБОР
КОГДА ВЫРАЗИТЬ(Данные.Значение КАК ЧИСЛО(15, 2)) ЕСТЬ NULL
ТОГДА 0
ИНАЧЕ ВЫРАЗИТЬ(Данные.Значение КАК ЧИСЛО(15, 2))
КОНЕЦ КАК ЗначениеЧислом
Третий вариант — хранить данные сразу в правильном типе. Если строковый реквизит по смыслу числовой, лучше изменить тип реквизита в конфигурации с конвертацией данных, чем вечно преобразовывать в каждом запросе.
Сравнение вариантов
Быстро для чистых данных; не справляется с запятыми, пробелами и буквами
Гибко, работает с любым форматом; требует больше кода и двух этапов
Лучшее решение на перспективу; требует изменения конфигурации и конвертации данных
Спасает итоги от NULL, но маскирует проблемные данные вместо их исправления
Типичные ошибки и ограничения
Первая ошибка — ожидание, что ВЫРАЗИТЬ «поймёт» любой формат. Она не парсер, а приведение типа, и требования к входной строке жёсткие. Вторая — слишком маленькая разрядность: ЧИСЛО(5, 0) для значений вроде 123456 приведёт к ошибке или обрезке. Третья — игнорирование NULL: при соединении таблиц по преобразованному полю строки с NULL просто выпадают из результата, и итоги не сходятся.
Отдельно стоит помнить про итоги и группировки: СУММА(ВЫРАЗИТЬ(...)) корректно работает только если все значения преобразовались. Один NULL не сломает сумму (NULL игнорируется агрегатными функциями), но результат будет занижен без какого-либо предупреждения.
Проверка результата преобразования
После внедрения преобразования полезно выполнить контроль: сравнить количество строк исходной выборки и количество непустых значений после приведения. Расхождение покажет объём «потерянных» данных. Для финансовых величин дополнительно сверяют сумму до (по очищенным значениям кодом) и после (в запросе).
Как проверить результат
Совпадает, NULL отсутствуют
Часть строк дала NULL — есть некорректные значения
Порядок 1, 2, 10, 25
Порядок 1, 10, 2, 25 — сортировка осталась строковой
Совпадает с контрольной суммой, посчитанной кодом
Сумма занижена — часть значений не преобразовалась
Что важно запомнить
Текст в число в запросе 1С преобразуется через ВЫРАЗИТЬ(Поле КАК ЧИСЛО(Длина, Точность)). Функция требует чистого числового формата с точкой; грязные данные дают NULL и требуют очистки кодом. Для регулярных задач надёжнее хранить значения в числовом реквизите.
Частые вопросы
Можно ли в запросе 1С использовать функцию Число() как во встроенном языке?
Нет, в языке запросов такой функции нет. Приведение выполняется только через ВЫРАЗИТЬ(... КАК ЧИСЛО(...)). Функция Число() доступна во встроенном языке и применяется при обработке данных вне запроса.
Почему ВЫРАЗИТЬ возвращает NULL вместо ошибки?
Таково поведение приведения типов в языке запросов: некорректное значение не прерывает выполнение, а превращается в NULL. Это удобно для устойчивости запроса, но требует явной проверки результата, иначе данные теряются незаметно.
Как преобразовать строку с запятой, например «123,45»?
В самом запросе надёжного способа нет. Очистите значение до запроса: во встроенном языке выполните СтрЗаменить(Значение, ",", ".") и передайте результат через временную таблицу, либо исправьте данные при загрузке в базу.
Влияет ли ВЫРАЗИТЬ на производительность запроса?
В списке выбираемых полей влияние небольшое. А вот в условиях ГДЕ и соединениях преобразование отключает использование индексов, и на больших таблицах запрос может выполняться в разы дольше. Для частых фильтров заведите числовой реквизит.
Как заменить NULL на ноль после преобразования?
Используйте функцию ЕСТЬNULL(ВЫРАЗИТЬ(Поле КАК ЧИСЛО(15, 2)), 0) — это короче конструкции ВЫБОР. Учтите, что ноль замаскирует проблемные исходные значения, поэтому параллельно стоит найти и исправить сами данные.
Работает ли приём в динамических списках и СКД?
Да, ВЫРАЗИТЬ поддерживается в тексте запроса динамического списка и в выражениях СКД, включая вычисляемые поля и ресурсы. Ограничения те же: чистый формат строки и осторожность с условиями на больших выборках.