Как получить пустое значение типа ХранилищеЗначения в запросе 1С

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

При работе с запросами в платформах 1С:Предприятие часто возникает необходимость сформировать составной результат, где некоторые поля должны содержать пустые значения определенных типов. Для ссылочных типов данных мы привыкли использовать системную конструкцию ЗНАЧЕНИЕ(Справочники.ИмяСправочника.ПустаяСсылка). Однако попытка получить аналогичным образом пустое поле типа ХранилищеЗначения вызывает вопросы и ошибки. Рассмотрим подробно, почему существует такое ограничение и какие альтернативные варианты решения задачи доступны разработчику.

Ограничения платформы 1С при работе с бинарными данными в запросах

Проанализируем архитектуру хранения данных в платформе 1С. Поля типа ХранилищеЗначения хранятся в СУБД как бинарные объекты большого объема (BLOB, varbinary(max) или bytea). Из-за особенностей работы СУБД с бинарными полями на уровне языка запросов 1С действует ряд жестких ограничений:

  1. Конструкция ЗНАЧЕНИЕ() поддерживает только системные перечисления, предопределенные элементы и пустые ссылки ссылочных типов. Для типа ХранилищеЗначения литералов в языке запросов не существует.
  2. Попытка передать объект типа ХранилищеЗначения в качестве параметра запроса через метод УстановитьПараметр() вызовет ошибку выполнения, так как платформа не передает бинарные хранилища напрямую в параметры SQL-запроса.
  3. Поля типа ХранилищеЗначения нельзя использовать в секциях ГДЕ, СГРУППИРОВАТЬ ПО, УПОРЯДОЧИТЬ ПО, в условиях соединений ПО, а также в конструкциях ВЫБРАТЬ РАЗЛИЧНЫЕ и ОБЪЕДИНИТЬ (допускается только ОБЪЕДИНИТЬ ВСЕ).

Таким образом, прямого способа создать и вернуть экземпляр ХранилищеЗначения средствами одного лишь языка запросов в 1С нет. Выясним, как эту проблему можно обойти на практике.

Вариант 1. Левое соединение с таблицей, содержащей пустое ХранилищеЗначения

Если в конфигурации есть справочник или регистр, в котором присутствует реквизит типа ХранилищеЗначения, и в базе гарантированно есть запись с незаполненным реквизитом, мы можем выполнить соединение с этой таблицей. При отсутствии совпадений в результате соединения поле вернет значение NULL, а при выборе из пустой записи СУБД вернет значение хранилища.

Рассмотрим пример запроса с соединением:


ВЫБРАТЬ
    МояТаблица.Ссылка КАК Ссылка,
    СохраненныеНастройки.ХранилищеНастроек КАК ПустоеХранилище
ИЗ
    Справочник.Номенклатура КАК МояТаблица
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.СохраненныеНастройки КАК СохраненныеНастройки
        ПО СохраненныеНастройки.Ссылка = ЗНАЧЕНИЕ(Справочник.СохраненныеНастройки.ПустаяСсылка)

Важное замечание: данный подход имеет существенный минус — полученное поле по-прежнему невозможно использовать в секциях группировки СГРУППИРОВАТЬ ПО или сортировки. По этой причине способ подходит только для простых выборок.

Вариант 2. Программная постобработка результата запроса

Более надежный и гибкий способ — не пытаться формировать ХранилищеЗначения внутри SQL-запроса, а выгрузить результат в ТаблицуЗначений и заполнить нужную колонку на стороне встроенного языка 1С.

Разберем данный алгоритм по шагам:

  1. В тексте запроса вместо хранилища выбираем значение НЕОПРЕДЕЛЕНО или NULL.
  2. Выгружаем результат запроса в объект ТаблицаЗначений.
  3. Изменяем тип колонки с помощью объекта ОписаниеТипов или заполняем строковые значения нужными экземплярами ХранилищеЗначения в цикле.

Посмотрим на пример реализации в коде:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Организации.Ссылка КАК Ссылка,
    |	НЕОПРЕДЕЛЕНО КАК Хранилище
    |ИЗ
    |	Справочник.Организации КАК Организации";

ТаблицаРезультата = Запрос.Выполнить().Выгрузить();

// При необходимости изменяем состав типов колонки
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("ХранилищеЗначения"));
ТаблицаРезультата.Колонки.Хранилище.ТипЗначений = Новый ОписаниеТипов(МассивТипов);

// Заполняем поле объектами хранилища
ПустоеХранилище = Новый ХранилищеЗначения(Неопределено);
Для Каждого СтрокаТЗ Из ТаблицаРезультата Цикл
    СтрокаТЗ.Хранилище = ПустоеХранилище;
КонецЦикла;

Вариант 3. Использование Системы компоновки данных (СКД)

Если задача заключается в формировании отчета или сложного набора данных с группировками, идеальным решением будет использование Системы компоновки данных. В СКД обработка полей производится процессором компоновки уже после получения данных из базы SQL.

В СКД вы можете:

  1. Использовать механизмы Вычисляемых полей, где в выражениях допускается вызов серверных экспортных функций общих модулей.
  2. Передавать бинарные данные в пользовательские функции встроенного языка 1С, вычислять хеш-суммы (например, с помощью объекта ХешированиеДанных) и производить любые необходимые трансформации.
  3. Выполнять группировку и агрегацию по исходным полям до того, как они будут преобразованы в бинарные объекты.

Таким образом, решение задачи зависит от конечной цели: для построения отчетов следует перенести логику в СКД, а для прикладных алгоритмов обработки данных — производить формирование объектов ХранилищеЗначения программно после выполнения запроса.

← На главную