Разработка и Конфигурация · 10 мин
Как преобразовать строку в число в запросе 1С 8.3
Способы преобразования строки в число в запросе 1С 8.3: ВЫРАЗИТЬ, соединение со справочником, ВЫБОР с ПОДСТРОКА. Примеры кода, ограничения и типичные ошибки.
Задача преобразовать строку в число прямо в тексте запроса возникает регулярно: данные пришли из обмена в строковом виде, код или артикул хранится как строка, а сравнивать и сортировать нужно как числа. Проблема в том, что язык запросов 1С 8.3 не содержит функции прямого приведения строки к числу — в отличие от встроенного языка, где есть Число().
Функция ВЫРАЗИТЬ(... КАК ЧИСЛО) умеет приводить только значения, которые уже имеют числовой тип (или NULL), и используется в основном для усечения разрядности. Попытка применить её к строке завершится ошибкой исполнения запроса. Поэтому приходится использовать обходные приёмы, и у каждого есть свои условия применимости и ограничения.
Ниже разобраны рабочие варианты: соединение со справочником, разбор строки через ПОДСТРОКА и ВЫБОР, перенос преобразования на уровень встроенного языка, а также способ «не преобразовывать вовсе», изменив постановку задачи. Для каждого приёма указано, когда он оправдан и где подводит.
Почему ВЫРАЗИТЬ не решает задачу
Конструкция ВЫРАЗИТЬ(Поле КАК ЧИСЛО(15, 2)) предназначена для двух вещей: усечь разрядность существующего числа и сузить составной тип поля до одного типа. Она не выполняет разбор текстового представления числа. Если передать в неё строковое поле, платформа при выполнении запроса выдаст ошибку о несовместимости типов.
Это принципиальное ограничение языка запросов: в нём вообще нет функций разбора строк (Число(), Дата() из встроенного языка в запросах недоступны). Поэтому любой способ преобразования — это либо подстановка числового значения из другого источника, либо посимвольная сборка числа из цифр.
Способ 1. Соединение со справочником или регистром
Самый надёжный приём — не преобразовывать строку, а найти соответствующее числовое значение в другой таблице. Типичный сценарий: строка — это код или артикул, по которому в справочнике есть числовой реквизит. Тогда вместо преобразования выполняется левое соединение, и в результат попадает уже число.
ВЫБРАТЬ
Товары.Артикул КАК Артикул,
СправочникАртикулов.ПорядковыйНомер КАК Номер
ИЗ
Документ.Реализация.Товары КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Артикулы КАК СправочникАртикулов
ПО Товары.Артикул = СправочникАртикулов.Код
Условие применимости: строковое значение должно однозначно совпадать с ключом в таблице соответствий. Обратите внимание на формат: если в строке ведущие нули, пробелы или другой регистр, соединение не сработает. Перед соединением строку часто приходится «чистить» — в запросе для этого доступна только ПОДСТРОКА, поэтому сложную нормализацию лучше делать заранее встроенным языком.
Плюс способа — корректная работа индексов и предсказуемая производительность. Минус — нужна таблица соответствий, которой может не быть.
Способ 2. Разбор строки через ПОДСТРОКА и ВЫБОР
Если строка гарантированно состоит из цифр известной длины, число можно собрать посимвольно: каждый символ через ВЫБОР превращается в цифру, которая умножается на разрядный вес и суммируется. Приём громоздкий, но работает полностью на стороне СУБД.
ВЫБРАТЬ
ВЫБОР
КОГДА ПОДСТРОКА(Данные.Код, 1, 1) = "1" ТОГДА 1000
КОГДА ПОДСТРОКА(Данные.Код, 1, 1) = "2" ТОГДА 2000
ИНАЧЕ 0
КОНЕЦ
+ ВЫБОР
КОГДА ПОДСТРОКА(Данные.Код, 2, 1) = "1" ТОГДА 100
КОГДА ПОДСТРОКА(Данные.Код, 2, 1) = "2" ТОГДА 200
ИНАЧЕ 0
КОНЕЦ КАК КодЧислом
ИЗ
РегистрСведений.Данные КАК Данные
Для полного перебора цифр 0–9 в каждом разряде потребуется по десять веток КОГДА. Реальный текст запроса быстро разрастается, поэтому такой код обычно генерируют программно — циклом встроенного языка собирают строку запроса под нужную длину числа.
Ограничения приёма существенные: длина строки должна быть фиксированной и небольшой (практически — до 6–8 разрядов), дробные числа и знак «минус» обрабатывать придётся отдельными ветками, а любой нецифровой символ молча превратится в ноль. Если в данных возможны «грязные» значения, результат нужно обязательно проверять.
Способ 3. Преобразование встроенным языком до или после запроса
Часто правильное решение — вынести преобразование за пределы запроса. Если строка участвует в условии отбора, преобразуйте параметр до выполнения: Запрос.УстановитьПараметр("Код", Число(СтрокаКода)). Функция Число() встроенного языка корректно разбирает строку, а при нечисловом значении выдаёт понятную ошибку, которую можно перехватить через Попытка...Исключение.
Второй вариант — обойти результат запроса и добавить вычисляемую колонку. Для таблицы значений это делается так: добавляется колонка с типом «Число», затем в цикле Для Каждого Строка Из Таблица Цикл заполняется через Число(Строка.СтроковоеПоле). Для СКД аналогичная задача решается вычисляемым полем на вкладке «Вычисляемые поля», где в выражении доступен встроенный язык.
- 1Выполните запрос и выгрузите результат в таблицу значений
- 2Добавьте колонку с описанием типа Число нужной длины и точности
- 3В цикле заполните колонку через Число() с обработкой исключений для нечисловых значений
- 4Проверьте выборочно несколько строк: число должно совпадать со строковым представлением
Этот подход медленнее чисто запросного на больших объёмах, зато универсален: работает с любым форматом строк, позволяет логировать проблемные значения и не ограничен длиной числа.
Способ 4. Перевернуть задачу: привести число к строке
Если цель — сравнить числовое поле со строковым (например, отобрать документы по строке с номером), иногда проще преобразовать не строку в число, а число в строку. В языке запросов нет и обратной функции форматирования, но число можно сопоставить со строковым представлением через тот же справочник-подстановку или через соединение, где строковое поле сравнивается с уже подготовленной строкой параметра.
Практический смысл: преобразование «число → строка» обычно выполняется один раз для параметра встроенным языком (Формат(ЧисловоеЗначение, "ЧГ=")), а не для каждой строки таблицы. Это на порядки дешевле, чем собирать числа из строк в каждой записи. Перед тем как строить сложный запрос, проверьте, нельзя ли переформулировать условие отбора таким образом.
Сравнение вариантов
Подходит, когда есть таблица соответствий строка-число. Быстро и надёжно, но требует такой таблицы
Работает только для строк фиксированной длины из чистых цифр. Запрос громоздкий, код генерируют программно
Универсально и безопасно, но требует обхода данных встроенным языком
Оптимально для условий отбора: одна операция вместо преобразования всей таблицы
Проверка результата и типичные ошибки
После любого приёма преобразования результат нужно верифицировать, потому что ошибки здесь не всегда приводят к падению запроса — чаще к тихо неверным данным. Минимальный контроль: выбрать несколько строк с известными значениями и сравнить исходную строку с полученным числом, а также проверить сумму или количество записей до и после преобразования.
Как проверить результат
Число равно значению строки, включая ведущие нули в исходнике
Число отличается или равно нулю там, где строка содержит цифры
Совпадает с количеством до соединения
Записей стало больше — дубли в таблице соответствий
Такие строки явно помечены или отфильтрованы
Нечисловые строки молча стали нулём
Отдельно стоит помнить про ведущие нули: строки «00123» и «0123» после преобразования дадут одно и то же число 123. Если это коды разных объектов, преобразование в число уничтожит различие между ними — и соединения по числовому полю начнут давать ложные совпадения.
Частые вопросы
Можно ли в запросе 1С отсортировать строковые коды как числа?
Напрямую — нет, сортировка строк идёт лексикографически: «10» окажется раньше «2». Варианты: добавить в запрос вычисляемое числовое поле одним из описанных способов и сортировать по нему, либо дополнить строки ведущими нулями до одинаковой длины ещё при записи данных — тогда строковая сортировка совпадёт с числовой.
Что вернёт Число() для строки с буквами?
Встроенная функция Число() при неразборчивой строке вызывает исключение «Преобразование значения к типу Число не может быть выполнено». Перехватите его через Попытка...Исключение и решите, что делать с такой записью: пропустить, записать ноль или залогировать для разбора.
Работает ли посимвольный разбор для дробных чисел?
Технически да, но запрос становится неприемлемо громоздким: нужно отдельно обработать целую и дробную части, найти позицию разделителя и учесть его тип (точка или запятая). Для дробных значений практически всегда разумнее преобразование встроенным языком.
Можно ли преобразовать строку в число в СКД?
Да, и это удобнее, чем в запросе. На закладке «Вычисляемые поля» добавьте поле с выражением на встроенном языке, например Число(СтроковоеПоле). Выражение выполняется для каждой строки результата, поэтому для больших выборок учитывайте стоимость обхода.
Почему соединение по строковому коду не находит совпадения?
Чаще всего причины в расхождении форматов: ведущие или конечные пробелы, разная длина кода с ведущими нулями, неразрывные пробелы из выгрузок, отличия регистра букв. Сравните значения через вычисление длины строки и посимвольный вывод — расхождение обычно видно сразу.
Есть ли разница в поведении на разных СУБД?
Конструкции языка запросов платформа транслирует на все поддерживаемые СУБД, поэтому набор доступных приёмов одинаков. Различия проявляются только в производительности тяжёлых запросов с большим числом веток ВЫБОР — на некоторых СУБД такие запросы оптимизируются хуже.
Что важно запомнить
Прямого приведения строки к числу в запросе 1С 8.3 нет. Выбирайте приём по ситуации: соединение со справочником — если есть таблица соответствий, ПОДСТРОКА с ВЫБОР — для коротких строк из чистых цифр, Число() встроенного языка — как универсальный вариант. Всегда проверяйте результат на контрольных записях и помните про ведущие нули.