При интеграции платформы 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', 'Котлета мясная');
Когда СУБД получает этот запрос, парсер должен обработать строковый литерал 'Котлета мясная'. На данном этапе СУБД руководствуется следующими правилами:
VARCHAR).SQL_Latin1_General_CP1_CI_AS (кодовая страница CP1252).?).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С выступает в роли генератора 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, необходимо явно сообщить платформе тип базы данных, к которой мы подключаемся.
Рассмотрим два сценария решения этой задачи: через конфигуратор и программно в коде.
Если подключение к внешнему источнику данных настроено статически в метаданных вашей конфигурации, выполните следующие шаги:
После этой простой настройки платформа начнет генерировать запросы с использованием префикса N.
Если вы инициализируете подключение к внешнему источнику программно (например, при запуске системы или в фоновом задании), вам необходимо обязательно заполнить свойство СУБД объекта ПараметрыСоединенияВнешнегоИсточникаДанных.
Рассмотрим подробный пример кода инициализации подключения:
// Создаем объект параметров соединения
ПараметрыСоединения = Новый ПараметрыСоединенияВнешнегоИсточникаДанных;
// Задаем строку подключения к 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 правильно распознает кириллические символы, и они будут сохранены в базе без каких-либо искажений.
Чтобы избежать других потенциальных проблем с кодировкой и производительностью при работе с внешними СУБД через 1С, рекомендуем придерживаться следующих правил:
ODBC Driver 17 for SQL Server или более новый ODBC Driver 18 for SQL Server. Старые драйверы вроде SQL Server Native Client 11.0 считаются устаревшими и могут некорректно обрабатывать Юникод-строки в некоторых конфигурациях.AutoTranslate=No;. Этот параметр предотвращает автоматическое перекодирование символов драйвером ODBC на основе системной локали Windows. Это особенно актуально, если сервер 1С работает под управлением англоязычной ОС или Linux, а СУБД настроена на русскую локаль.NVARCHAR вместо VARCHAR и NCHAR вместо CHAR для всех текстовых полей, где предполагается хранение русских букв.Мы успешно проанализировали проблему с кодировкой при интеграции 1С и СУБД Azure SQL. Как видите, решение заключается всего лишь в одной строке кода или одной настройке в конфигураторе, которая указывает платформе верный тип СУБД и активирует правильный диалект T-SQL с автоматическим добавлением Юникод-префиксов.