При написании запросов в платформе 1С:Предприятие разработчики часто используют предопределенную функцию ЗНАЧЕНИЕ для получения пустых ссылок, системных перечислений или предопределенных элементов. Однако если случайно или намеренно опустить указание конкретного элемента или свойства ПустаяСсылка и написать, например, ЗНАЧЕНИЕ(Справочник.ДоговорыКонтрагентов), платформа возвратит неожиданный результат — шестнадцатеричный код или значение, приводящее к сбою при выгрузке запроса. Разберем по шагам, почему так происходит, что именно скрывается за этим результатом и как правильно работать с типами и пустыми ссылками в запросах 1С.
Проанализируем ситуацию, когда в тексте запроса используется обращение к метаданным без уточнения элемента:
ВЫБРАТЬ
ЗНАЧЕНИЕ(Справочник.Контрагенты) КАК ПолеТипа
В консоли запросов разработчик может увидеть шестнадцатеричное значение вида 08 00 00 83 либо Неопределено (в зависимости от клиента и способа отображения). Выясним причину такого поведения:
ЗНАЧЕНИЕ(Справочник.Имя) как литерал типа данных, что полностью эквивалентно вызову функции ТИП(Справочник.Имя).08 00 00 83) — это бинарный код типа объекта метаданных. Платформа 1С использует его на уровне таблиц базы данных для хранения и идентификации типов в полях составного типа (Reference-поля), где отдельно хранится код таблицы и отдельно GUID ссылки.Посмотрим на пример логической проверки, подтверждающей эту эквивалентность:
ВЫБРАТЬ
ВЫБОР
КОГДА ЗНАЧЕНИЕ(Справочник.Контрагенты) = ТИП(Справочник.Контрагенты)
ТОГДА ИСТИНА
ИНАЧЕ ЛОЖЬ
КОНЕЦ КАК РезультатСравнения
Такой запрос вернет значение Истина, что наглядно доказывает равенство литерала типа и обращения к объекту метаданных внутри конструкции ЗНАЧЕНИЕ.
Рассмотрим распространенную проблему: запрос с конструкцией ЗНАЧЕНИЕ(Справочник.Имя) в блоке ВЫБРАТЬ успешно выполняется на сервере баз данных, но при попытке выгрузить результат во встроенном языке происходит аварийное завершение:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗНАЧЕНИЕ(Справочник.Контрагенты) КАК ТипОбъекта,
| ТИПЗНАЧЕНИЯ(ЗНАЧЕНИЕ(Справочник.Контрагенты)) КАК ТипЗначенияПоля";
Выборка = Запрос.Выполнить();
ТаблицаРезультата = Выборка.Выгрузить(); // Вызывает системную ошибку
Причина ошибки заключается в том, что платформа 1С не поддерживает маршалинг и сериализацию «сырых» бинарных литералов типов метаданных в стандартные типы встроенного языка для колонок объекта ТаблицаЗначений. Литералы типов в языке запросов спроектированы исключительно для вычислений внутри сервера баз данных (в секциях ГДЕ, КОГДА ... ТОГДА, СОЕДИНЕНИЕ), а не для передачи в выходной набор колонок.
Если цель запроса состояла в получении пустой ссылки на справочник, документ или иной ссылочный тип, необходимо явно указывать свойство пустой ссылки. Разберем правильный синтаксис:
ВЫБРАТЬ
ЗНАЧЕНИЕ(Справочник.ДоговорыКонтрагентов.ПустаяСсылка) КАК ПустойДоговор,
ЗНАЧЕНИЕ(Документ.РеализацияТоваровУслуг.ПустаяСсылка) КАК ПустаяРеализация
Важно: В некоторых версиях платформы допускается сокращенная запись с точкой на конце — ЗНАЧЕНИЕ(Справочник.ДоговорыКонтрагентов.), однако для повышения читаемости и надежности программного кода всегда рекомендуется использовать полное явное указание: .ПустаяСсылка.
Когда требуется проверить тип поля составного типа или привести значение к конкретной таблице метаданных, рассмотрим стандартные и проверенные практики платформы 1С:
ВЫБРАТЬ
Взаиморасчеты.Документ,
ВЫБОР
КОГДА Взаиморасчеты.Документ ССЫЛКА Документ.РеализацияТоваровУслуг
ТОГДА "Реализация"
КОГДА Взаиморасчеты.Документ ССЫЛКА Документ.ПоступлениеТоваровУслуг
ТОГДА "Поступление"
ИНАЧЕ "Прочее"
КОНЕЦ КАК ВидДокумента
ИЗ
РегистрНакопления.ВзаиморасчетыСКонтрагентами КАК Взаиморасчеты
ВЫБРАТЬ
Задачи.Объект
ИЗ
Задача.ЗадачиПользователя КАК Задачи
ГДЕ
ТИПЗНАЧЕНИЯ(Задачи.Объект) = ТИП(Справочник.Контрагенты)
ВЫРАЗИТЬ:
ВЫБРАТЬ
ВЫРАЗИТЬ(Задачи.Объект КАК Справочник.Контрагенты).ИНН КАК ИННКонтрагента
ИЗ
Задача.ЗадачиПользователя КАК Задачи
Тип:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СкладскиеОстатки.Номенклатура
|ИЗ
| РегистрНакопления.ТоварыНаСкладах КАК СкладскиеОстатки
|ГДЕ
| ТИПЗНАЧЕНИЯ(СкладскиеОстатки.Номенклатура) = &ИскомыйТип";
Запрос.УстановитьПараметр("ИскомыйТип", Тип("СправочникСсылка.Номенклатура"));
Результат = Запрос.Выполнить();
Таким образом, конструкция ЗНАЧЕНИЕ(Справочник.Имя) возвращает бинарный литерал типа метаданных, который не предназначен для прямой выгрузки в результат запроса. Для ссылок следует применять ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка), а для фильтрации типов — оператор ССЫЛКА или функцию ТИП.