Почему функция ЕСТЬNULL в запросе 1С обрезает строку и как это исправить?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При написании запросов в 1С разработчики нередко сталкиваются с неожиданным поведением функции ЕСТЬNULL(). Типичная ситуация: в качестве значения замены для отсутствующего значения передается длинная строка, однако на выходе получается строка, обрезанная ровно до длины проверяемого поля. Разберем, почему платформа ведет себя именно так, выясним причину на уровне трансляции запросов в СУБД и рассмотрим надежные способы обхода этого ограничения.

В чем проявляется проблема: смотрим на пример

Представим, что в конфигурации длина кода справочника Сотрудники составляет 9 символов. В запросе требуется подставить заглушку из длинной последовательности символов, если сотрудник не найден:


ВЫБРАТЬ
    ЕСТЬNULL(Сотрудники.Код, "9999999999999999999999999999") КАК КодСотрудника
ИЗ
    Документ.НачислениеЗарплаты.Начисления КАК Начисления
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Сотрудники КАК Сотрудники
        ПО Начисления.Сотрудник = Сотрудники.Ссылка

В результате выполнения такого запроса поле КодСотрудника вместо переданной длинной строки возвращает ровно 9 символов: "999999999". Создается впечатление, что ЕСТЬNULL() самовольно ограничивает длину результата. Проанализируем механизм работы платформы и разберемся, является ли это ошибкой.

Выясним причину: правила приведения типов и трансляция в SQL

Подобное поведение заложено в платформу изначально и описано в стандартах разработки 1С. Функция ЕСТЬNULL() языка запросов не является полным аналогом конструкции ВЫБОР КОГДА. Главное отличие состоит в строгой типизации: если первое выражение функции имеет строковый или числовой тип, то значение второго выражения неявно приводится к типу и разрядности первого проверяемого выражения.

Рассмотрим, как запрос преобразуется на уровне систем управления базами данных (СУБД):

  1. В среде Microsoft SQL Server: функция ЕСТЬNULL() в большинстве случаев транслируется в штатную функцию СУБД ISNULL(check_expression, replacement_value). Согласно спецификации T-SQL, эта функция всегда возвращает тип данных первого аргумента. Если тип или длина второго аргумента больше, СУБД автоматически отсекает лишние символы без генерации ошибки.
  2. В среде PostgreSQL: хотя операция транслируется через COALESCE(), генератор запросов 1С принудительно накладывает операторы явного приведения типов CAST к параметрам первого аргумента, чтобы поведение запросов оставалось идентичным независимо от используемой СУБД.
  3. Поведение с числами: если для строковых данных происходит безопасное усечение справа, то при несовпадении числовых типов поведение еще строже. Если дробная часть значения замены превышает разрядность поля, она отсекается или округляется, а при превышении целой части запрос может завершиться критической ошибкой переполнения на стороне СУБД.

Таким образом, ЕСТЬNULL() ориентируется исключительно на левый операнд. Посмотрим на проверенные способы решения этой проблемы.

Способ 1. Искусственное расширение длины первого поля через ВЫРАЗИТЬ

Если мы хотим продолжить использовать компактную функцию ЕСТЬNULL(), нам необходимо явно расширить размерность первого параметра. Для этого обернем первое поле в оператор ВЫРАЗИТЬ с требуемой длиной строки:


ВЫБРАТЬ
    ЕСТЬNULL(ВЫРАЗИТЬ(Сотрудники.Код КАК СТРОКА(30)), "9999999999999999999999999999") КАК КодСотрудника
ИЗ
    Справочник.Сотрудники КАК Сотрудники

Обратите внимание: расширять тип нужно именно внутри первого аргумента ЕСТЬNULL(). Если попытаться применить ВЫРАЗИТЬ снаружи ко всей функции целиком, это не даст результата, так как усечение произойдет до внешнего преобразования.

Способ 2. Замена на конструкцию ВЫБОР КОГДА

Наиболее универсальным и стандартным подходом является отказ от ЕСТЬNULL() в пользу полной конструкции ВЫБОР КОГДА. Разберем пример реализации:


ВЫБРАТЬ
    ВЫБОР
        КОГДА Сотрудники.Код ЕСТЬ NULL
            ТОГДА "9999999999999999999999999999"
        ИНАЧЕ Сотрудники.Код
    КОНЕЦ КАК КодСотрудника
ИЗ
    Справочник.Сотрудники КАК Сотрудники

Проанализируем преимущества этой конструкции:

  1. В отличие от ЕСТЬNULL(), оператор ВЫБОР при определении типа результирующей колонки анализирует все ветки условий (ТОГДА и ИНАЧЕ).
  2. Итоговая длина строкового поля вычисляется по максимальной длине среди всех возвращаемых значений, благодаря чему строка подстановки никогда не будет обрезана.
  3. Запрос транслируется в SQL через конструкцию CASE WHEN, что гарантирует корректную работу даже при несовпадении типов данных.

Способ 3. Перенос оформления в Систему компоновки данных (СКД)

Если запрос разрабатывается для отчета на СКД, перегружать текст запроса приведением типов ради вывода пользовательского текста не рекомендуется. Рассмотрим, как решить задачу штатными средствами компоновки:

  1. В запросе оставляем исходное поле без изменений.
  2. На закладке Настройки в разделе Условное оформление добавляем новое правило.
  3. В условии указываем проверку поля на незаполненность (Поле Не Заполнено).
  4. В оформлении активируем параметр Текст и задаем строку, которая должна выводиться пользователю вместо пустого значения.

Такой подход избавляет от лишних вычислений в СУБД и сохраняет исходные типы полей неизменными для дальнейшей обработки и группировки данных.

← На главную