В какой кодировке хранятся данные в MS SQL 1C и как правильно читать бинарные ссылки?

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

При работе с базами данных 1С:Предприятие на уровне SQL-запросов разработчики часто сталкиваются с тем, что данные выглядят «нечитаемыми». Особенно это касается ссылочных полей, таких как _IDRRef. В этой статье мы подробно разберем, в каких кодировках 1С хранит строковые данные, почему ссылки представлены в бинарном виде и как правильно преобразовать их в привычный GUID с помощью SQL и внешних инструментов.

Кодировка строковых данных в MS SQL Server для 1С

Начнем с базового вопроса кодировок. Разберем ситуацию, когда мы пытаемся понять, как именно текст попадает в таблицы базы данных. В MS SQL Server для баз данных 1С строковые данные всегда хранятся в кодировке Unicode. Рассмотрим подробнее основные технические параметры:

  1. Типы данных: 1С использует типы NVARCHAR и NCHAR для хранения текстовой информации. Эти типы используют двухбайтовую кодировку UCS-2 (которая является подмножеством UTF-16). Это позволяет платформе корректно отображать символы любых алфавитов в одном поле.
  2. Collation (Параметры сортировки): При установке MS SQL Server и создании базы данных 1С требует выбора определенного Collation. Чаще всего это Cyrillic_General_CI_AS.
    • CI (Case Insensitive) — означает, что поиск и сравнение строк будут регистронезависимыми (буквы "А" и "а" эквивалентны).
    • AS (Accent Sensitive) — означает чувствительность к ударениям.

Проанализируем типичную ошибку: если вы видите «кракозябры» при выборке данных через внешние скрипты (например, на PHP или Python), это чаще всего означает, что драйвер подключения пытается интерпретировать Unicode-строку как однобайтовую кодировку (Windows-1251 или UTF-8) без должного декодирования.

Бинарные данные и загадочное поле _IDRRef

Выясним причину, по которой ссылки 1С выглядят как набор странных символов. Рассмотрим поле _IDRRef. Это поле имеет тип binary(16). Оно представляет собой 16-байтовый идентификатор (GUID), который в 1С соответствует уникальной ссылке на объект.

Многие начинающие разработчики пытаются прочитать это поле как обычную строку, получая результат вида „Ќј®Е6љ6.... Это происходит потому, что любая программа пытается отобразить «сырые» байты через текущую кодовую таблицу. На самом деле, это не текст, а шестнадцатеричное число.

Специфика хранения GUID в 1С: перестановка байтов

Самый важный и сложный момент при работе с _IDRRef — это так называемое «перемешивание байтов». Проанализируем ситуацию: 1С хранит GUID в SQL-базе не в том порядке, в котором мы видим его в программном коде String(Ссылка.УникальныйИдентификатор()).

Зачем это нужно? 1С оптимизирует работу индексов MS SQL Server. В стандартном GUID (RFC 4122) младшие байты, которые меняются чаще всего, стоят в начале. Если записывать их в индекс «как есть», это приведет к сильной фрагментации индекса при добавлении новых записей. 1С переносит эти «динамичные» байты в конец, превращая случайную вставку в последовательную. Это значительно повышает производительность дисковой подсистемы.

Рассмотрим схему трансформации байтов. Если мы имеем стандартный GUID, разбитый на группы: 1-2-3-4-5, то в SQL поле _IDRRef он будет храниться в порядке: 4-5-3-2-1. Точнее, последние 8 байт перемещаются в начало, а первые блоки байтов — в конец и частично инвертируются.

Как прочитать GUID прямым SQL-запросом?

Если нам нужно получить читаемую строку идентификатора прямо в консоли SQL Management Studio или через PHP, мы можем воспользоваться функцией CONVERT. Разберем пример запроса:


SELECT 
    TOP 10
    _Description, 
    CONVERT(NVARCHAR(MAX), _IDRRef, 2) AS GUID_As_Hex
FROM 
    _Reference10; -- Пример таблицы справочника

В данном примере параметр 2 в функции CONVERT указывает SQL-серверу преобразовать бинарные данные в шестнадцатеричную строку без префикса 0x. Полученная строка всё еще будет иметь «перепутанный» порядок байтов 1С, но её уже можно использовать для поиска или программной обработки.

Программная реконструкция GUID (пример на языке 1С)

Разберем, как выглядит алгоритм «сборки» нормального идентификатора из массива байтов, полученного из SQL. Рассмотрим пример кода, который выполняет обратную перестановку:


// Предположим, А - это массив байтов (binary), полученный из SQL
// Создадим таблицу соответствия шестнадцатеричных значений
Ч16 = Новый Массив(256);
Символы16 = "0123456789abcdef";
Для Сч = 0 По 255 Цикл
    Ч16[Сч] = Сред(Символы16, Цел(Сч / 16) + 1, 1) + Сред(Символы16, Сч % 16 + 1, 1);
КонецЦикла;

// Собираем строку GUID в формате RFC 4122, переставляя индексы
// 1С хранит: 0-7 байты (стандартные 8-15), 8-15 байты (стандартные 0-7 в обратном порядке)
Результат = Ч16[А[12]] + Ч16[А[13]] + Ч16[А[14]] + Ч16[А[15]] + "-" + 
            Ч16[А[10]] + Ч16[А[11]] + "-" + 
            Ч16[А[8]] + Ч16[А[9]] + "-" + 
            Ч16[А[0]] + Ч16[А[1]] + "-" + 
            Ч16[А[2]] + Ч16[А[3]] + Ч16[А[4]] + Ч16[А[5]] + Ч16[А[6]] + Ч16[А[7]];

Этот код наглядно показывает, какие именно байты нужно поменять местами, чтобы сопоставить данные в SQL-таблице с конкретным объектом в интерфейсе 1С.

Особенности работы через PHP

Выясним, как избежать проблем при работе с бинарными данными в PHP. Если вы используете драйвер sqlsrv, важно помнить, что по умолчанию он может пытаться привести binary(16) к строке, что приведет к потере данных. Рекомендуется использовать параметры привязки типов:

  1. При выполнении запроса указывайте SQLSRV_ENC_BINARY для получения «сырого» потока байтов.
  2. Используйте функцию bin2hex() для перевода полученного результата в строку.
  3. После этого примените алгоритм перестановки символов, аналогичный приведенному выше, чтобы получить валидный GUID.

Прямые запросы или веб-сервисы?

Посмотрим на ситуацию с точки зрения архитектуры. В обсуждении упоминалось использование веб-сервисов как альтернативы прямым запросам. Разберем плюсы и минусы обоих подходов:

Прямые SQL-запросы:

Веб-сервисы (REST/SOAP):

Проанализировав всё вышесказанное, можно сделать вывод: если ваша задача — быстрая интеграция или построение сложных отчетов на внешних системах, использование CONVERT и понимание структуры _IDRRef являются необходимыми навыками. Если же важна надежность и простота — лучше использовать штатные механизмы 1С.

← На главную