При работе с запросами в платформах 1С:Предприятие часто возникает необходимость сформировать составной результат, где некоторые поля должны содержать пустые значения определенных типов. Для ссылочных типов данных мы привыкли использовать системную конструкцию ЗНАЧЕНИЕ(Справочники.ИмяСправочника.ПустаяСсылка). Однако попытка получить аналогичным образом пустое поле типа ХранилищеЗначения вызывает вопросы и ошибки. Рассмотрим подробно, почему существует такое ограничение и какие альтернативные варианты решения задачи доступны разработчику.
Проанализируем архитектуру хранения данных в платформе 1С. Поля типа ХранилищеЗначения хранятся в СУБД как бинарные объекты большого объема (BLOB, varbinary(max) или bytea). Из-за особенностей работы СУБД с бинарными полями на уровне языка запросов 1С действует ряд жестких ограничений:
ЗНАЧЕНИЕ() поддерживает только системные перечисления, предопределенные элементы и пустые ссылки ссылочных типов. Для типа ХранилищеЗначения литералов в языке запросов не существует.ХранилищеЗначения в качестве параметра запроса через метод УстановитьПараметр() вызовет ошибку выполнения, так как платформа не передает бинарные хранилища напрямую в параметры SQL-запроса.ХранилищеЗначения нельзя использовать в секциях ГДЕ, СГРУППИРОВАТЬ ПО, УПОРЯДОЧИТЬ ПО, в условиях соединений ПО, а также в конструкциях ВЫБРАТЬ РАЗЛИЧНЫЕ и ОБЪЕДИНИТЬ (допускается только ОБЪЕДИНИТЬ ВСЕ).Таким образом, прямого способа создать и вернуть экземпляр ХранилищеЗначения средствами одного лишь языка запросов в 1С нет. Выясним, как эту проблему можно обойти на практике.
Если в конфигурации есть справочник или регистр, в котором присутствует реквизит типа ХранилищеЗначения, и в базе гарантированно есть запись с незаполненным реквизитом, мы можем выполнить соединение с этой таблицей. При отсутствии совпадений в результате соединения поле вернет значение NULL, а при выборе из пустой записи СУБД вернет значение хранилища.
Рассмотрим пример запроса с соединением:
ВЫБРАТЬ
МояТаблица.Ссылка КАК Ссылка,
СохраненныеНастройки.ХранилищеНастроек КАК ПустоеХранилище
ИЗ
Справочник.Номенклатура КАК МояТаблица
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.СохраненныеНастройки КАК СохраненныеНастройки
ПО СохраненныеНастройки.Ссылка = ЗНАЧЕНИЕ(Справочник.СохраненныеНастройки.ПустаяСсылка)
Важное замечание: данный подход имеет существенный минус — полученное поле по-прежнему невозможно использовать в секциях группировки СГРУППИРОВАТЬ ПО или сортировки. По этой причине способ подходит только для простых выборок.
Более надежный и гибкий способ — не пытаться формировать ХранилищеЗначения внутри SQL-запроса, а выгрузить результат в ТаблицуЗначений и заполнить нужную колонку на стороне встроенного языка 1С.
Разберем данный алгоритм по шагам:
НЕОПРЕДЕЛЕНО или NULL.ТаблицаЗначений.ОписаниеТипов или заполняем строковые значения нужными экземплярами ХранилищеЗначения в цикле.Посмотрим на пример реализации в коде:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Организации.Ссылка КАК Ссылка,
| НЕОПРЕДЕЛЕНО КАК Хранилище
|ИЗ
| Справочник.Организации КАК Организации";
ТаблицаРезультата = Запрос.Выполнить().Выгрузить();
// При необходимости изменяем состав типов колонки
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("ХранилищеЗначения"));
ТаблицаРезультата.Колонки.Хранилище.ТипЗначений = Новый ОписаниеТипов(МассивТипов);
// Заполняем поле объектами хранилища
ПустоеХранилище = Новый ХранилищеЗначения(Неопределено);
Для Каждого СтрокаТЗ Из ТаблицаРезультата Цикл
СтрокаТЗ.Хранилище = ПустоеХранилище;
КонецЦикла;
Если задача заключается в формировании отчета или сложного набора данных с группировками, идеальным решением будет использование Системы компоновки данных. В СКД обработка полей производится процессором компоновки уже после получения данных из базы SQL.
В СКД вы можете:
ХешированиеДанных) и производить любые необходимые трансформации.Таким образом, решение задачи зависит от конечной цели: для построения отчетов следует перенести логику в СКД, а для прикладных алгоритмов обработки данных — производить формирование объектов ХранилищеЗначения программно после выполнения запроса.