Разработка и Конфигурация · 10 мин
Запрос 1С как число: приведение типов в запросах
Как в запросе 1С привести значение к числу: ВЫРАЗИТЬ КАК ЧИСЛО, работа со строками, NULL, составными типами. Примеры, ошибки и проверка результата.
Задача привести значение к числу в запросе 1С возникает постоянно: данные хранятся строкой, поле имеет составной тип, результат вычисления нужно округлить до заданной точности, а сравнение «строки с числом» молча возвращает пустой результат. В языке запросов 1С нет функции «Число()» как во встроенном языке — вместо неё используется оператор ВЫРАЗИТЬ ... КАК ЧИСЛО(длина, точность), и у него есть важные ограничения.
Главное ограничение: ВЫРАЗИТЬ не выполняет преобразование строки в число. Если поле хранит «123,45» как строку, попытка выразить её как число даст NULL, а не число. Оператор предназначен для другого — сузить составной тип, отбросить лишние типы, задать точность и длину числового поля, привести NULL к нужному типу для корректной работы соединений и группировок.
Ниже разобраны рабочие приёмы: синтаксис ВЫРАЗИТЬ, приведение составных типов, обходные пути для строк с числами, работа с NULL, типичные ошибки и способы проверить результат до того, как запрос уйдёт в рабочую базу.
Синтаксис ВЫРАЗИТЬ КАК ЧИСЛО и зачем он нужен
Оператор ВЫРАЗИТЬ записывается так: ВЫРАЗИТЬ(Поле КАК ЧИСЛО(15, 2)), где первый параметр типа — общая длина числа (максимум 38), второй — количество знаков после запятой. Например, ЧИСЛО(15, 2) — число до 15 разрядов, из которых 2 отведены под дробную часть.
Основные сценарии применения: сузить составной тип поля до одного числового типа, задать разрядность результата агрегатной функции или вычисляемого поля, привести NULL к числовому типу, чтобы итоги и соединения работали предсказуемо. Без явного приведения составное поле в группировке или соединении может дать неожиданные результаты — платформа сравнивает значения с учётом типа.
ВЫБРАТЬ
ВЫРАЗИТЬ(Регистр.Количество КАК ЧИСЛО(15, 3)) КАК Количество,
ВЫРАЗИТЬ(Регистр.Сумма / Регистр.Количество КАК ЧИСЛО(15, 2)) КАК Цена
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки КАК РегистрОбратите внимание на второе поле примера: деление в запросе может дать число с «хвостом» из множества знаков. Приведение к ЧИСЛО(15, 2) обрезает результат до копеек прямо в запросе, без постобработки в коде.
Приведение составного типа к числу
Типичная ситуация: реквизит объявлен как составной тип (число, строка, ссылка), а по нему нужно посчитать сумму или выполнить сравнение. Платформа не сможет корректно сгруппировать или отфильтровать такое поле, пока тип не сужен. ВЫРАЗИТЬ(Поле КАК ЧИСЛО(15, 2)) оставляет только числовые значения, всё остальное превращается в NULL.
Важно понимать: значения других типов не «исчезают с ошибкой», а становятся NULL. Если половина строк хранит строки, а не числа, сумма по приведённому полю будет занижена без какого-либо предупреждения. Перед приведением имеет смысл проверить, какие типы реально лежат в поле, запросом с функцией ТИПЗНАЧЕНИЯ(Поле).
Проверка типов до приведения
Запрос вида ВЫБРАТЬ ТИПЗНАЧЕНИЯ(Поле) КАК Тип, КОЛИЧЕСТВО(*) КАК Количество ... СГРУППИРОВАТЬ ПО ТИПЗНАЧЕНИЯ(Поле) покажет фактическое распределение типов. Если в поле оказались строки с числами, их потребуется обработать отдельно — об этом следующий раздел.
Строка с числом: почему ВЫРАЗИТЬ не поможет и что делать
Язык запросов 1С не содержит функции преобразования строки в число. ВЫРАЗИТЬ("123" КАК ЧИСЛО) вернёт NULL, потому что оператор не преобразует, а только сужает тип. Это принципиальное ограничение платформы, а не ошибка синтаксиса.
Рабочих подхода три. Первый — привести данные на этапе записи: исправить процедуру, которая кладёт числа в строковый реквизит, и разово переконвертировать накопленные данные обработкой. Это самый надёжный вариант, если данные ваши и структуру можно менять.
Второй — выгрузить результат запроса в таблицу значений и в цикле присвоить колонке числовые значения функцией встроенного языка Число() с проверкой через ОписаниеТипов и попыткой преобразования. Третий — разобрать строку в запросе через ПОДСТРОКА и ВЫБОР КОГДА, складывая разряды: приём громоздкий, работает только для целых чисел известной максимальной длины, но иногда это единственный вариант, когда постобработка недоступна (например, в СКД без кода).
Как выбрать подход
NULL, ЕСТЬNULL и приведение типа пустого значения
NULL в запросе не имеет типа, и это создаёт проблемы: соединение по NULL-полю не сработает, сравнение с NULL всегда ложно, а в итоговой таблице колонка может получить непредсказуемый составной тип. Приведение через ВЫРАЗИТЬ фиксирует тип колонки: ВЫРАЗИТЬ(ЕСТЬNULL(Поле, 0) КАК ЧИСЛО(15, 2)) — стандартная связка для левых соединений.
Порядок важен: сначала ЕСТЬNULL заменяет пустоту нулём, затем ВЫРАЗИТЬ задаёт тип. Если поменять местами, результат обычно тот же, но связка «ЕСТЬNULL внутри» читается однозначнее и не зависит от нюансов оптимизатора. Для параметров запроса, которые могут быть не заполнены, также полезно приводить тип явно — это ускоряет выполнение и упрощает план запроса СУБД.
Округление и точность вычислений
Округление в запросе выполняется тем же ВЫРАЗИТЬ: приведение к ЧИСЛО(15, 2) отбрасывает лишние разряды по правилам округления платформы. Отдельной функции «Окр» в языке запросов нет. Если нужно округление вверх или вниз, используют арифметический трюк: прибавить или вычесть 0,5 и привести к целому, либо выполнить округление уже в коде после выгрузки.
При делении следите за тем, чтобы знаменатель не был нулём — деление на ноль в запросе вызывает ошибку выполнения. Защита стандартная: ВЫБОР КОГДА Знаменатель = 0 ТОГДА 0 ИНАЧЕ Числитель / Знаменатель КОНЕЦ, и уже результат при необходимости приводится к нужной точности.
- 1Определите фактический тип поля запросом с ТИПЗНАЧЕНИЯ
- 2Если тип числовой или составной с числами — примените ВЫРАЗИТЬ КАК ЧИСЛО(длина, точность)
- 3Оберните поле в ЕСТЬNULL, если возможны пустые значения из соединений
- 4Защитите деление проверкой знаменателя через ВЫБОР КОГДА
- 5Выполните запрос на копии и проверьте долю NULL и контрольные суммы
Проверка результата и типичные ошибки
После изменения запроса проверьте три вещи: тип результирующей колонки (через ТипЗначения при обходе выборки или в консоли запросов), количество строк до и после приведения, контрольную сумму по известному набору данных. Расхождение суммы после приведения почти всегда означает, что часть значений была нечисловой и превратилась в NULL.
Как проверить результат
Число с заданной длиной и точностью
Составной тип или строка — приведение не сработало
NULL только там, где значения изначально пустые
NULL появились у строк с данными — в поле нечисловые значения
Совпадает с суммой, посчитанной до приведения по числовым значениям
Сумма меньше — часть данных потеряна при сужении типа
Отдельная частая ошибка — слишком маленькая разрядность. Если суммы в базе достигают сотен миллионов с копейками, ЧИСЛО(10, 2) не вместит значение, и запрос упадёт с ошибкой переполнения. Для денежных величин безопасный минимум — ЧИСЛО(15, 2), для курсов и коэффициентов — ЧИСЛО(15, 4) или точнее.
В консоли запросов удобно тестировать приведение на одной строке: добавьте условие по конкретному документу, проверьте тип и значение колонки, и только потом убирайте фильтр. Это быстрее, чем отлаживать полный запрос по всей таблице.
FAQ
Можно ли в запросе 1С преобразовать строку в число напрямую?
Нет, функции преобразования строки в число в языке запросов нет. ВЫРАЗИТЬ КАК ЧИСЛО вернёт NULL для строкового значения. Варианты обхода: исправить данные при записи, преобразовать колонку после выгрузки в таблицу значений функцией Число() или собрать число из разрядов через ВЫБОР КОГДА и ПОДСТРОКА для коротких целых чисел.
Что означают параметры ЧИСЛО(15, 2)?
Первое число — общая максимальная длина значения в разрядах (до 38), второе — количество разрядов дробной части. ЧИСЛО(15, 2) хранит до 13 разрядов в целой части и 2 после запятой. Целая часть не может превышать разность длины и точности.
Почему после ВЫРАЗИТЬ КАК ЧИСЛО часть значений стала NULL?
Потому что в поле лежали значения нечисловых типов — строки, ссылки, даты. ВЫРАЗИТЬ не преобразует их, а отбрасывает, возвращая NULL. Проверьте распределение типов запросом с ТИПЗНАЧЕНИЯ и решите, как обрабатывать нечисловые значения.
Как округлить число в запросе до двух знаков?
Примените ВЫРАЗИТЬ(Значение КАК ЧИСЛО(15, 2)) — лишние разряды будут отброшены с округлением. Отдельной функции округления в языке запросов нет. Для округления в большую или меньшую сторону используйте арифметику (прибавить 0,5 и привести к целому) или округляйте в коде после выгрузки.
Зачем приводить к числу параметр запроса?
Явное приведение типа параметра убирает неоднозначность составного типа, упрощает план выполнения на стороне СУБД и защищает от ситуации, когда незаполненный параметр получает неподходящий тип. Это особенно заметно на больших таблицах и в виртуальных таблицах регистров.
Чем отличается ВЫРАЗИТЬ в запросе от Число() в коде?
ВЫРАЗИТЬ работает внутри запроса и только сужает тип до числового, не преобразуя строки. Функция Число() встроенного языка реально преобразует строковое представление в число, но применяется уже к результату запроса в коде, а не в тексте запроса.
Что важно запомнить
Приведение к числу в запросе 1С делается через ВЫРАЗИТЬ(Поле КАК ЧИСЛО(длина, точность)). Оператор сужает составной тип и задаёт разрядность, но не превращает строку в число — такие значения станут NULL. Перед приведением проверяйте типы через ТИПЗНАЧЕНИЯ, защищайте соединения через ЕСТЬNULL, а строки с числами обрабатывайте на этапе записи данных или после выгрузки в таблицу значений.