Как исправить некорректную кодировку при получении текстовых данных из MS SQL в 1С

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

При интеграции 1С со сторонними базами данных на платформе MS SQL Server разработчики часто используют прямое подключение через COM-объект ADODB.Connection. В большинстве случаев числа, даты и короткие строки считываются без нареканий. Однако при попытке прочитать определенные текстовые поля (комментарии, описания задач, длинные примечания) вместо читаемого текста на кириллице в 1С возвращается набор нечитаемых знаков или знаков вопроса, хотя в SQL Server Management Studio (SSMS) этот же запрос отображает данные корректно.

Разберем детально, почему возникает эта ошибка и какими способами можно получить корректные строковые данные в 1С.

Выясним причину возникновения проблемы

Проанализируем механизм передачи строковых данных из MS SQL в среду 1С:Предприятие. Основная причина сбоя заключается в том, как драйверы доступа к данным и COM-модель ADO работают с большими неструктурированными полями (LOB — Large Object):

  1. Особенности типов text, ntext, varchar(max) и nvarchar(max): В объектной модели ADODB поля неограниченной длины распознаются как потоковые типы данных (adLongVarChar или adLongVarWChar). При прямом обращении через свойство Поле.Value механизм COM-маршалинга между ADO и платформой 1С не всегда может корректно преобразовать указатель на поток в стандартную Unicode-строку (BSTR). В результате байты считываются со смещением или неверной интерпретацией длины, что приводит к искажению символов.
  2. Использование ODBC-драйвера вместо прямого OLE DB: Если в строке подключения указан синтаксис вида DRIVER={SQL Server Native Client 11.0}, взаимодействие происходит через промежуточный мост (MSDASQL к ODBC), который исторически испытывает трудности при передаче полей с модификатором MAX напрямую в COM-свойства.
  3. Параметры автотрансляции кодовых страниц: При несовпадении параметров сортировки (Collation) таблицы и локали операционной системы может происходить нежелательное перекодирование текста драйвером клиента.

Способ 1. Явное приведение типов в SQL-запросе (Быстрое решение)

Рассмотрим самое простое и эффективное решение проблемы, не требующее изменения конфигурации драйверов на сервере. Если максимальная длина текста в поле заведомо не превышает 4000 символов, приведем поле к фиксированному типу Юникод-строки nvarchar(4000) прямо в тексте запроса или в представлении (View) на стороне SQL Server.

Посмотрим на пример формирования SQL-запроса в коде 1С:


Соединение = Новый COMОбъект("ADODB.Connection");
Соединение.ConnectionString = "DRIVER={SQL Server Native Client 11.0};SERVER=" + Объект.Сервер + ";UID=" + Объект.Пользователь + ";PWD=" + Объект.Пароль + ";DATABASE=" + Объект.База + ";";
Соединение.Open();

Команда = Новый COMОбъект("ADODB.Command");
Команда.ActiveConnection = Соединение;

// Приводим поле Comments типа varchar(max)/text к nvarchar(4000)
Команда.CommandText = 
    "SELECT 
    |    ID, 
    |    CAST(Comments AS nvarchar(4000)) AS TaskComments 
    |FROM dbo.Tasks";

Выборка = Команда.Execute();

Пока Выборка.EOF() = 0 Цикл
    ТекстКомментария = Выборка.Fields("TaskComments").Value;
    Сообщить("Комментарий: " + ТекстКомментария);
    Выборка.MoveNext();
КонецЦикла;

Выборка.Close();
Соединение.Close();

Важное ограничение: Тип nvarchar(4000) вмещает до 4 000 символов. Если исходный текст в базе данных длиннее, SQL Server выполнит неявное усечение (обрезку) строки без вывода ошибки. Если критично получать тексты большего объема, рассмотрим альтернативные варианты.

Способ 2. Переход на прямой OLE DB провайдер в строке подключения

Разберем изменение параметров подключения. Отказ от ODBC-драйвера в пользу прямого OLE DB провайдера позволяет избавиться от промежуточных уровней трансляции и корректно передавать длинные Unicode-поля в COM-интерфейс 1С.

Посмотрим, как изменить строку подключения:


// Вариант 1: Использование SQL Server Native Client OLE DB Provider
СтрокаПодключения = "Provider=SQLNCLI11;Server=" + Объект.Сервер + ";Database=" + Объект.База + ";Uid=" + Объект.Пользователь + ";Pwd=" + Объект.Пароль + ";DataTypeCompatibility=80;";

// Вариант 2: Использование современного Microsoft OLE DB Driver for SQL Server (MSOLEDBSQL)
// СтрокаПодключения = "Provider=MSOLEDBSQL;Server=" + Объект.Сервер + ";Database=" + Объект.База + ";UID=" + Объект.Пользователь + ";PWD=" + Объект.Пароль + ";";

Соединение = Новый COMОбъект("ADODB.Connection");
Соединение.ConnectionString = СтрокаПодключения;
Соединение.Open();

Параметр DataTypeCompatibility=80 сообщает провайдеру о необходимости приведения новых типов данных (включая varchar(max)) к классическим форматам, которые без сбоев воспринимаются стандартными COM-библиотеками.

Способ 3. Постраничное чтение данных через GetChunk

Если в базе хранятся большие блоки текста неограниченного размера и мы не можем использовать CAST с фиксированной длиной, прочитаем значение поля по частям с помощью встроенного метода ADO GetChunk.

Рассмотрим пример чтения длинного текста порциями:


Функция ПрочитатьДлинныйТекстИзПоля(ПолеADO, РазмерБуфера = 4000)
    ПолныйТекст = "";
    ОбщийРазмер = ПолеADO.ActualSize;
    
    Если ОбщийРазмер = 0 Тогда
        Возврат "";
    КонецЕсли;
    
    СчитаноБайт = 0;
    Пока СчитаноБайт < ОбщийРазмер Цикл
        КусокТекста = ПолеADO.GetChunk(РазмерБуфера);
        Если КусокТекста = Неопределено Тогда
            Прервать;
        КонецЕсли;
        ПолныйТекст = ПолныйТекст + Строка(КусокТекста);
        СчитаноБайт = СчитаноБайт + РазмерБуфера;
    КонецЦикла;
    
    Возврат ПолныйТекст;
КонецФункции

Способ 4. Использование механизма «Внешние источники данных» платформы 1С

Проанализируем современный штатный подход платформы 1С:Предприятие 8.3. Вместо ручной работы с COM-объектами ADODB.Connection и ADODB.Recordset рекомендуется использовать объект метаданных Внешние источники данных:

  1. В дереве конфигурации в ветке Внешние источники данных добавим новый источник.
  2. Настроим подключение через системный DSN или строку соединения ODBC.
  3. С помощью мастера добавим нужные таблицы из базы MS SQL.
  4. Платформа 1С автоматически сопоставит типы varchar(max) и nvarchar(max) с типом Строка неограниченной длины.
  5. После этого чтение данных выполняется стандартными запросами 1С без проблем с кодировками:

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    Задачи.ID КАК ID,
    |    Задачи.Comments КАК Comments
    |ИЗ
    |    ВнешнийИсточникДанных.ВнешняяБаза.Таблица.dbo_Tasks КАК Задачи";

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

Пока Выборка.Следующий() Цикл
    Сообщить("Комментарий: " + Выборка.Comments);
КонецЦикла;

Использование внешних источников данных полностью исключает влияние COM-маршалинга и гарантирует корректное отображение любых текстовых полей вне зависимости от настроек драйвера.

← На главную