При прямой интеграции с базой данных 1С на уровне СУБД часто возникает задача прочитать данные из таблиц, где реквизиты имеют тип ХранилищеЗначения. В физической структуре MS SQL Server такие поля имеют тип varbinary(max). Попытка выполнить стандартное приведение типов с помощью CAST или CONVERT к строковому представлению возвращает набор нечитаемых символов или шестнадцатеричный дамп.
Разберем подробно, как платформа 1С сохраняет бинарные объекты в базе данных, почему обычное преобразование в SQL не работает и какими способами можно получить исходное значение.
Проанализируем ситуацию на примере выполнения SQL-запроса к таблице регистра сведений:
DECLARE @b VARBINARY(MAX);
SET @b = 0x0201534B6FF4888DC14EA0D5EBB6BDA0...;
SELECT CAST(@b AS VARCHAR(MAX));
В результате такого преобразования возвращается не исходная строка или XML-структура, а бинарная «каша». Причина заключается в том, что платформа 1С перед сохранением данных в ХранилищеЗначения упаковывает их с использованием алгоритма сжатия (Deflate/zlib).
Рассмотрим структуру бинарного блока, хранящегося в поле varbinary(max):
0x02 указывает на то, что полезная нагрузка упакована алгоритмом сжатия Deflate. Байт 0x01 обозначает хранение данных без сжатия.Встроенная функция MS SQL Server DECOMPRESS() (доступная с SQL Server 2016) не может распаковать эти данные «из коробки», так как ожидает стандартный заголовок RFC 1952 (GZIP), которого в структуре 1С нет.
Если необходимо выполнять чтение и распаковку непосредственно на стороне СУБД в рамках хранимых процедур или представлений, эффективным решением является написание пользовательской CLR-функции на C#.
Разберем логику работы такой функции по шагам:
SqlBytes (бинарные данные из поля varbinary(max)).0x02), отсекаем байты служебного заголовка платформы (смещение обычно составляет 1–2 байта).DeflateStream в режиме декомпрессии.NVARCHAR(MAX) с использованием кодировки UTF-8.Если данные извлекаются во внешнюю систему через коннекторы ADO, ODBC или специализированные ETL-пайплайны, распаковку проще выполнять на стороне клиентского приложения.
Посмотрим на пример логики на языке Python с использованием библиотеки zlib:
import zlib
def decompress_1c_blob(raw_data: bytes) -> str:
# Проверяем наличие флага сжатия 1С
if raw_data[0] == 2:
# Отсекаем заголовок и передаем raw deflate поток
decompressed = zlib.decompress(raw_data[2:], -zlib.MAX_WBITS)
else:
decompressed = raw_data[1:]
return decompressed.decode('utf-8', errors='ignore')
Использование параметра -zlib.MAX_WBITS указывает библиотеке на отсутствие стандартных заголовков zlib/gzip, что позволяет успешно восстановить полезную нагрузку 1С.
Если обработка данных происходит внутри инфраструктуры 1С, наиболее надежным и штатным способом является использование стандартных объектов платформы. Это исключает риски нарушения лицензионного соглашения и защищает решение от сбоев при обновлении конфигурации.
Посмотрим, как извлечь значение из объекта ХранилищеЗначения средствами языка 1С:
Хранилище = Выборка.Строения; // Поле типа ХранилищеЗначения
Если Хранилище <> Неопределено Тогда
ИсходныеДанные = Хранилище.Получить();
// ИсходныеДанные содержат строку, структуру или двоичные данные в исходном виде
КонецЕсли;
Прямое чтение таблиц СУБД в обход сервера 1С несет существенные риски: имена таблиц (_InfoRgXXXX) и полей (_FldXXXX) изменяются при реструктуризации и обновлениях, а формат внутреннего сжатия не документирован вендором. Для интеграции рекомендуется использовать штатные механизмы:
ВнешниеИсточникиДанных.