Кодировка текста при выгрузке из 1С в SQL через ADO: как избежать иероглифов и знаков вопроса

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

При интеграции систем на платформе 1С:Предприятие с внешними базами данных MS SQL Server напрямую через технологию ADO (ActiveX Data Objects) разработчики регулярно сталкиваются с проблемой искажения текстовых данных. Русские буквы при записи в таблицы SQL превращаются в нечитаемые символы, «кракозябры» или знаки вопроса (???). Особенно часто это происходит при работе со старыми конфигурациями (например, «Зарплата и управление персоналом КОРП, редакция 2.5») на обычных формах.

В этой статье мы подробно разберем, почему возникают подобные сбои, как правильно настроить строку подключения ADO, и какие подходы в написании SQL-запросов гарантируют стопроцентное сохранение исходной кодировки кириллицы.

Почему параметр Charset не работает в строке подключения к SQL Server

Первое побуждение программиста при возникновении проблем с кодировкой — добавить параметр charset=windows-1251 или charset=utf-8 прямо в строку соединения (Connection String) ADO. Однако при работе с провайдером данных MS SQL Server (будь то классический SQLOLEDB.1 или современный MSOLEDBSQL) этот параметр будет проигнорирован.

Дело в том, что OLE DB провайдеры для SQL Server принципиально не поддерживают аргумент charset в строке подключения. Данный параметр предназначен исключительно для работы с текстовыми файлами (например, через драйверы Jet/ACE OLE DB) или для объекта ADODB.Stream. В случае со СУБД MS SQL кодировка передаваемых данных зависит от параметров сортировки (Collation) базы данных, типов целевых полей на сервере и системных региональных настроек ОС на стороне клиента.

Решение 1. Тонкая настройка строки подключения ADO

Чтобы драйвер ADO корректно транслировал однобайтовую кириллицу (Windows-1251) в неюникодовые поля базы данных (тип VARCHAR), мы должны явно управлять параметрами автоматического перевода символов в строке подключения.

Для этого в строку соединения необходимо добавить два ключевых параметра:

  1. Auto Translate=True (или AutoTranslate=True) — эта опция указывает драйверу выполнять автоматическую конвертацию символов OEM/ANSI между кодовой страницей клиентского компьютера (где запущена 1С) и кодовой страницей сервера СУБД. Если кодовые страницы различаются, включение этого флага предотвратит появление знаков вопроса.
  2. Tag with column collation when possible=True — заставляет OLE DB провайдер использовать параметры сортировки (Collation) конкретной колонки таблицы SQL при передаче текстовых данных.

Пример правильно сформированной строки подключения для провайдера SQLOLEDB.1:


СтрокаПодключения = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;"
                    + "Initial Catalog=ИмяБазыДанных;Data Source=ИмяСервера;"
                    + "Auto Translate=True;Tag with column collation when possible=True;";

Решение 2. Использование Юникода и префикса N в запросах

Платформа 1С:Предприятие по умолчанию хранит и обрабатывает все текстовые строки исключительно в формате Юникод (UTF-16). Проблемы с кодировкой чаще всего начинаются в момент трансляции строки из 1С в СУБД внутри динамически собираемого SQL-запроса.

Если на стороне SQL Server поле таблицы имеет тип VARCHAR, данные записываются в однобайтовой кодировке. Если же поле имеет тип NVARCHAR (нативный Юникод в SQL Server), то любые проблемы с кодировкой исключены при одном важнейшем условии: строковые литералы в запросах должны предваряться префиксом N.

Рассмотрим ситуацию на примере. Допустим, мы пытаемся записать строку напрямую через SQL-запрос обновления:


// Неправильный вариант (может привести к потере кириллицы):
ЗапросТекст = "UPDATE MyTable SET Comment = '" + ТекстИз1С + "' WHERE ID = 1";

// Правильный вариант (с префиксом N):
ЗапросТекст = "UPDATE MyTable SET Comment = N'" + ТекстИз1С + "' WHERE ID = 1";

Без указания префикса N перед открывающей кавычкой SQL Server воспринимает переданную строку как обычный ANSI-текст. Он пытается предварительно преобразовать её в кодовую страницу по умолчанию вашей базы данных еще до физической записи в таблицу. Если кодировка базы отличается от кириллической (например, установлена Latin1_General), русские буквы безвозвратно превратятся в знаки вопроса даже в поле типа NVARCHAR.

Решение 3. Использование параметризованных запросов (ADODB.Command)

Самым надежным, безопасным и профессиональным способом решения любых проблем с кодировками является полный отказ от ручной склейки SQL-запросов и переход к параметризованным запросам с использованием объекта ADODB.Command.

Когда мы передаем текстовые переменные через параметры, драйвер ADO самостоятельно осуществляет бинарную передачу данных в Юникоде. Нам больше не нужно заботиться о префиксах N и экранировании кавычек в тексте 1С.

Рассмотрим пример реализации параметризованного запроса на языке 1С:


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

Command = Новый COMОбъект("ADODB.Command");
Command.ActiveConnection = Connection;
Command.CommandType = 1; // adCmdText

// Подготавливаем текст запроса с плейсхолдерами (?)
Command.CommandText = "INSERT INTO Employees (FIO, Description) VALUES (?, ?)";

// Создаем параметры с явным указанием типов Юникода
// Значение 202 соответствует типу adVarWChar (юникод-строка переменной длины)
ParamFIO = Command.CreateParameter("FIO", 202, 1, 150, "Иванов Петр Сидорович");
Command.Parameters.Append(ParamFIO);

// Для длинного текста используем тип adLongVarWChar (значение 203)
ParamDesc = Command.CreateParameter("Description", 203, 1, -1, "Подробное описание сотрудника из базы 1С");
Command.Parameters.Append(ParamDesc);

// Выполняем запись
Command.Execute();
Connection.Close();

При таком подходе СУБД гарантированно примет текст в исходном виде, автоматически выполнив корректное преобразование типов на уровне ядра SQL Server.

Решение 4. Переход на современный драйвер MSOLEDBSQL

Используемый по привычке во многих обработках провайдер SQLOLEDB.1 официально признан корпорацией Microsoft устаревшим (Deprecated). Он не поддерживает современные стандарты безопасности и новые возможности работы со строковыми типами данных (такими как UTF-8, появившаяся в MS SQL Server 2019).

Рекомендуется устанавливать на клиентских компьютерах актуальный драйвер Microsoft OLE DB Driver for SQL Server (MSOLEDBSQL). При его использовании строка подключения в 1С примет следующий вид:


СтрокаПодключения = "Provider=MSOLEDBSQL;DataTypeCompatibility=80;"
                    + "Data Source=ИмяСервера;Initial Catalog=ИмяБазы;"
                    + "Integrated Security=SSPI;Auto Translate=True;";

Параметр DataTypeCompatibility=80 крайне важен — он обеспечивает совместимость новых типов данных со старыми библиотеками ADO, исключая системные ошибки при чтении сложных полей.

Альтернативный вариант: Выгрузка через файл скрипта

Если под «прямой выгрузкой» подразумевается генерация текстового файла со скриптами SQL для его последующего пакетного выполнения, то кодировкой можно управлять на этапе записи самого файла. Для этого идеально подходит объект ADODB.Stream, позволяющий жестко зафиксировать необходимую кодовую страницу (например, Windows-1251):


ПутьКФайлу = "C:\Export\upload.sql";
Поток = Новый COMОбъект("ADODB.Stream");
Поток.Type = 2; // Текстовый формат
Поток.Charset = "windows-1251"; // Указываем целевую кодировку
Поток.Open();

СтрокаЗапроса = "INSERT INTO MyTable (Name) VALUES (N'" + СокрЛП(Выборка.Наименование) + "');" + Символы.ПС;
Поток.WriteText(СтрокаЗапроса);

Поток.SaveToFile(ПутьКФайлу, 2); // 2 - перезаписывать файл при наличии
Поток.Close();

Подведем итоги

Для полного устранения проблем с отображением кириллицы при выгрузке данных из 1С в MS SQL по каналам ADO придерживайтесь следующих правил:

← На главную