Как решить проблему с кодировкой (знаками вопроса) при работе 1С с СУБД Azure SQL через внешние источники данных

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

При интеграции платформы 1С:Предприятие 8.3 с внешними базами данных под управлением Microsoft SQL Server или облачного решения Azure SQL Database разработчики часто сталкиваются с неприятной проблемой. При записи текстовой информации, содержащей кириллицу, в таблицах внешней СУБД вместо русских букв появляются цепочки из знаков вопроса (????????). При этом чтение латинских символов и цифр происходит абсолютно корректно.

В этой статье мы подробно разберем, почему возникает эта ошибка, проанализируем внутренние механизмы СУБД и транслятора запросов 1С, а также рассмотрим пошаговое и элегантное решение этой проблемы без необходимости изменения структуры и параметров самой базы данных в Azure.

Почему вместо русских букв записываются знаки вопроса?

Для того чтобы понять суть проблемы, нам необходимо углубиться в то, как Microsoft SQL Server (и его облачная версия Azure SQL) обрабатывает строковые литералы на этапе выполнения SQL-запроса.

Рассмотрим стандартный запрос на добавление записи в таблицу:

INSERT INTO dbo.Segment (Id, Segment) VALUES ('6', 'Котлета мясная');

Когда СУБД получает этот запрос, парсер должен обработать строковый литерал 'Котлета мясная'. На данном этапе СУБД руководствуется следующими правилами:

  1. Анализ типа литерала: Строка заключена в обычные одинарные кавычки без дополнительных префиксов. Это сигнализирует СУБД о том, что данные передаются в формате не-Юникод (тип данных VARCHAR).
  2. Использование кодовой страницы по умолчанию (Collation): Для преобразования байтового потока в символы СУБД использует кодовую страницу (сортировку/collation), установленную для текущей базы данных. На облачных серверах Azure SQL базовой кодировкой по умолчанию часто является западноевропейская SQL_Latin1_General_CP1_CI_AS (кодовая страница CP1252).
  3. Потеря символов: Так как кодовая страница CP1252 (Latin1) физически не содержит символов кириллицы, парсер СУБД не может сопоставить байты русских букв ни с одним из доступных символов. В результате все неподдерживаемые символы безвозвратно заменяются на знаки вопроса (?).
  4. Запись в таблицу: Даже если целевое поле в таблице имеет тип NVARCHAR (поддерживающий Юникод и кириллицу), в него записывается уже испорченная на этапе парсинга строка, состоящая из знаков вопроса.

Для решения этой проблемы в языке T-SQL существует явный префикс Юникода — символ N (от слова National). Если мы модифицируем запрос следующим образом:

INSERT INTO dbo.Segment (Id, Segment) VALUES ('6', N'Котлета мясная');

СУБД сразу поймет, что строка передается в формате Юникод (UTF-16), проигнорирует кодировку по умолчанию SQL_Latin1_General_CP1_CI_AS и корректно запишет русские буквы в поле типа NVARCHAR.

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

Анализ поведения платформы 1С:Предприятие

В процессе работы с внешними источниками данных платформа 1С выступает в роли генератора SQL-запросов. Она транслирует объектные вызовы (например, метод Записать()) в низкоуровневые SQL-инструкции для конкретного драйвера ODBC.

Если при настройке внешнего источника данных не указать точный тип СУБД, с которой осуществляется взаимодействие, платформа 1С переходит в режим «совместимости» и начинает генерировать универсальные ANSI-совместимые запросы (Generic SQL). В этом режиме 1С не использует специфические конструкции конкретных баз данных. В стандарте ANSI SQL префикс N для строковых констант не является обязательным для всех СУБД, поэтому транслятор 1С его опускает. На сервер СУБД отправляются запросы вида:

INSERT INTO "dbo"."Segment" ("Id", "Segment") VALUES ('6', 'Котлета мясная')

Это и приводит к появлению знаков вопроса, если база данных в Azure настроена на латинскую кодировку.

Решение проблемы: Явное указание типа СУБД

Чтобы заставить платформу 1С использовать диалект T-SQL и корректно оборачивать все строковые литералы в Юникод-префикс N, необходимо явно сообщить платформе тип базы данных, к которой мы подключаемся.

Рассмотрим два сценария решения этой задачи: через конфигуратор и программно в коде.

Вариант 1. Настройка свойств подключения в конфигураторе

Если подключение к внешнему источнику данных настроено статически в метаданных вашей конфигурации, выполните следующие шаги:

  1. Откройте конфигуратор вашей информационной базы.
  2. В дереве метаданных найдите ветку Внешние источники данных и откройте свойства вашего источника.
  3. Перейдите к параметрам соединения.
  4. Найдите свойство Тип СУБД (или аналогичную настройку в зависимости от версии платформы) и принудительно выберите значение MSSQLServer (вместо пустого значения или значения "Универсальный").
  5. Сохраните конфигурацию базы данных.

После этой простой настройки платформа начнет генерировать запросы с использованием префикса N.

Вариант 2. Программное указание параметров подключения

Если вы инициализируете подключение к внешнему источнику программно (например, при запуске системы или в фоновом задании), вам необходимо обязательно заполнить свойство СУБД объекта ПараметрыСоединенияВнешнегоИсточникаДанных.

Рассмотрим подробный пример кода инициализации подключения:


// Создаем объект параметров соединения
ПараметрыСоединения = Новый ПараметрыСоединенияВнешнегоИсточникаДанных;

// Задаем строку подключения к Azure SQL Database
ПараметрыСоединения.СтрокаСоединения = 
    "DRIVER={ODBC Driver 17 for SQL Server};" +
    "SERVER=tcp:enotzharitkotlety.database.windows.net,1433;" +
    "UID=vasyapupkin@enotzharitkotlety;" +
    "PWD=12345678;" +
    "DATABASE=myaso;" +
    "LANGUAGE=русский;" +
    "AutoTranslate=No;";

// Указываем учетные данные напрямую в свойствах (рекомендуется для стабильности работы драйвера)
ПараметрыСоединения.ИмяПользователя = "vasyapupkin@enotzharitkotlety";
ПараметрыСоединения.Пароль = "12345678";

// КРИТИЧЕСКИ ВАЖНАЯ СТРОКА: Указываем тип СУБД
// Это заставит транслятор 1С использовать префикс "N" для строковых литералов
ПараметрыСоединения.СУБД = "MSSQLServer";

Попытка
    // Устанавливаем параметры для конкретного внешнего источника данных
    ВнешниеИсточникиДанных.ИмяВашегоВнешнегоИсточника.УстановитьОбщиеПараметрыСоединения(ПараметрыСоединения);
    
    // Подключаемся к базе данных
    ВнешниеИсточникиДанных.ИмяВашегоВнешнегоИсточника.УстановитьСоединение();
    
    ЗаписьЖурналаРегистрации("ПодключениеКAzure", УровеньЖурналаРегистрации.Информация, , , 
        "Соединение с Azure SQL успешно установлено.");
Исключение
    ЗаписьЖурналаРегистрации("ПодключениеКAzure", УровеньЖурналаРегистрации.Ошибка, , , 
        "Ошибка подключения: " + ОписаниеОшибки());
    ВызватьИсключение "Не удалось подключиться к базе данных Azure. Обратитесь к администратору.";
КонецПопытки;

После указания свойства ПараметрыСоединения.СУБД = "MSSQLServer" логи СУБД покажут, что запросы вставки и изменения данных теперь выглядят корректно:


INSERT INTO #tt1 ("_Id","_Segment") VALUES
(6, N'Вася'),
(1, N'Петя'),
(2, N'Жора');

Благодаря префиксу N СУБД Azure SQL правильно распознает кириллические символы, и они будут сохранены в базе без каких-либо искажений.

Дополнительные рекомендации по работе с Azure SQL и ODBC

Чтобы избежать других потенциальных проблем с кодировкой и производительностью при работе с внешними СУБД через 1С, рекомендуем придерживаться следующих правил:

  1. Используйте современные ODBC-драйверы: Убедитесь, что на сервере 1С (или на локальной машине при клиентском подключении) установлен актуальный драйвер. Рекомендуется использовать ODBC Driver 17 for SQL Server или более новый ODBC Driver 18 for SQL Server. Старые драйверы вроде SQL Server Native Client 11.0 считаются устаревшими и могут некорректно обрабатывать Юникод-строки в некоторых конфигурациях.
  2. Параметр AutoTranslate: В строке подключения рекомендуется использовать параметр AutoTranslate=No;. Этот параметр предотвращает автоматическое перекодирование символов драйвером ODBC на основе системной локали Windows. Это особенно актуально, если сервер 1С работает под управлением англоязычной ОС или Linux, а СУБД настроена на русскую локаль.
  3. Типы данных в СУБД: При проектировании таблиц во внешних базах всегда используйте типы данных NVARCHAR вместо VARCHAR и NCHAR вместо CHAR для всех текстовых полей, где предполагается хранение русских букв.

Мы успешно проанализировали проблему с кодировкой при интеграции 1С и СУБД Azure SQL. Как видите, решение заключается всего лишь в одной строке кода или одной настройке в конфигураторе, которая указывает платформе верный тип СУБД и активирует правильный диалект T-SQL с автоматическим добавлением Юникод-префиксов.

← На главную