При написании запросов в 1С разработчики нередко сталкиваются с неожиданным поведением функции ЕСТЬNULL(). Типичная ситуация: в качестве значения замены для отсутствующего значения передается длинная строка, однако на выходе получается строка, обрезанная ровно до длины проверяемого поля. Разберем, почему платформа ведет себя именно так, выясним причину на уровне трансляции запросов в СУБД и рассмотрим надежные способы обхода этого ограничения.
Представим, что в конфигурации длина кода справочника Сотрудники составляет 9 символов. В запросе требуется подставить заглушку из длинной последовательности символов, если сотрудник не найден:
ВЫБРАТЬ
ЕСТЬNULL(Сотрудники.Код, "9999999999999999999999999999") КАК КодСотрудника
ИЗ
Документ.НачислениеЗарплаты.Начисления КАК Начисления
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Сотрудники КАК Сотрудники
ПО Начисления.Сотрудник = Сотрудники.Ссылка
В результате выполнения такого запроса поле КодСотрудника вместо переданной длинной строки возвращает ровно 9 символов: "999999999". Создается впечатление, что ЕСТЬNULL() самовольно ограничивает длину результата. Проанализируем механизм работы платформы и разберемся, является ли это ошибкой.
Подобное поведение заложено в платформу изначально и описано в стандартах разработки 1С. Функция ЕСТЬNULL() языка запросов не является полным аналогом конструкции ВЫБОР КОГДА. Главное отличие состоит в строгой типизации: если первое выражение функции имеет строковый или числовой тип, то значение второго выражения неявно приводится к типу и разрядности первого проверяемого выражения.
Рассмотрим, как запрос преобразуется на уровне систем управления базами данных (СУБД):
ЕСТЬNULL() в большинстве случаев транслируется в штатную функцию СУБД ISNULL(check_expression, replacement_value). Согласно спецификации T-SQL, эта функция всегда возвращает тип данных первого аргумента. Если тип или длина второго аргумента больше, СУБД автоматически отсекает лишние символы без генерации ошибки.COALESCE(), генератор запросов 1С принудительно накладывает операторы явного приведения типов CAST к параметрам первого аргумента, чтобы поведение запросов оставалось идентичным независимо от используемой СУБД.Таким образом, ЕСТЬNULL() ориентируется исключительно на левый операнд. Посмотрим на проверенные способы решения этой проблемы.
Если мы хотим продолжить использовать компактную функцию ЕСТЬNULL(), нам необходимо явно расширить размерность первого параметра. Для этого обернем первое поле в оператор ВЫРАЗИТЬ с требуемой длиной строки:
ВЫБРАТЬ
ЕСТЬNULL(ВЫРАЗИТЬ(Сотрудники.Код КАК СТРОКА(30)), "9999999999999999999999999999") КАК КодСотрудника
ИЗ
Справочник.Сотрудники КАК Сотрудники
Обратите внимание: расширять тип нужно именно внутри первого аргумента ЕСТЬNULL(). Если попытаться применить ВЫРАЗИТЬ снаружи ко всей функции целиком, это не даст результата, так как усечение произойдет до внешнего преобразования.
Наиболее универсальным и стандартным подходом является отказ от ЕСТЬNULL() в пользу полной конструкции ВЫБОР КОГДА. Разберем пример реализации:
ВЫБРАТЬ
ВЫБОР
КОГДА Сотрудники.Код ЕСТЬ NULL
ТОГДА "9999999999999999999999999999"
ИНАЧЕ Сотрудники.Код
КОНЕЦ КАК КодСотрудника
ИЗ
Справочник.Сотрудники КАК Сотрудники
Проанализируем преимущества этой конструкции:
ЕСТЬNULL(), оператор ВЫБОР при определении типа результирующей колонки анализирует все ветки условий (ТОГДА и ИНАЧЕ).CASE WHEN, что гарантирует корректную работу даже при несовпадении типов данных.Если запрос разрабатывается для отчета на СКД, перегружать текст запроса приведением типов ради вывода пользовательского текста не рекомендуется. Рассмотрим, как решить задачу штатными средствами компоновки:
Поле Не Заполнено).Такой подход избавляет от лишних вычислений в СУБД и сохраняет исходные типы полей неизменными для дальнейшей обработки и группировки данных.