Как исправить знаки вопроса (?) вместо русских букв при запросе из 1С к базе Oracle

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

При интеграции «1С:Предприятия» с внешними базами данных часто используются прямые SQL-запросы через механизмы Microsoft ADO (ActiveX Data Objects). Однако разработчики регулярно сталкиваются со следующей проблемой: соединение устанавливается успешно, запрос выполняется без ошибок, но при попытке прочитать строковые данные из таблиц СУБД Oracle вместо привычной кириллицы выводятся знаки вопроса (?). Для изучения типовых сценариев настройки прямых запросов можно использовать руководство по подключению и получению данных из SQL в 1С.

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

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

Появление знаков вопроса вместо букв — это классический симптом рассинхронизации кодировок между сервером базы данных Oracle, установленным клиентом Oracle (Oracle Client) на машине с 1С и самим приложением «1С:Предприятие».

Когда вы выполняете запрос из 1С через COM-объект ADODB.Connection, цепочка передачи данных выглядит следующим образом:

  1. Сервер Oracle хранит текстовые данные в определенной кодировке (например, AL32UTF8 или CL8MSWIN1251).
  2. Клиентская часть Oracle (драйвер ODBC или OLE DB), установленная на сервере 1С, запрашивает эти данные.
  3. Клиентский драйвер должен перекодировать полученные от сервера байты в кодировку, понятную операционной системе Windows и приложению 1С.
  4. Если драйвер клиента Oracle не настроен должным образом, он выполняет конвертацию некорректно или использует стандартную кодировку ASCII (которая не поддерживает русские символы). В результате все символы за пределами стандартной латиницы превращаются в нечитаемые знаки вопроса.

Для управления поведением клиента Oracle используется ключевой параметр — NLS_LANG. Именно он сообщает драйверу, в каком языковом стандарте и в какой кодовой странице нужно возвращать текстовые данные.

Рассмотрим по шагам все возможные способы решения этой проблемы в зависимости от используемой архитектуры и прав доступа.

Решение 1. Настройка переменной окружения NLS_LANG (Основной способ)

Наиболее надежный и проверенный способ решить проблему с кодировкой — жестко задать системную переменную среды NLS_LANG на компьютере, где выполняется код 1С (это может быть либо локальный компьютер пользователя, либо сервер приложений 1С).

Формат значения переменной NLS_LANG выглядит так:

[Язык]_[Территория].[Кодировка]

Для русскоязычных пользователей Windows наиболее стабильным и подходящим значением является:

AMERICAN_AMERICA.CL8MSWIN1251 или RUSSIAN_RUSSIA.CL8MSWIN1251

Разберем процесс настройки по шагам:

  1. Откройте «Свойства системы» на сервере 1С (или рабочей машине). Быстро сделать это можно через сочетание клавиш Win + Break или выполнив команду sysdm.cpl в строке «Выполнить» (Win + R).
  2. Перейдите на вкладку «Дополнительно» и нажмите кнопку «Переменные среды».
  3. В разделе «Системные переменные» (нижнее окно) нажмите кнопку «Создать».
  4. Введите имя переменной: NLS_LANG.
  5. Введите значение переменной: AMERICAN_AMERICA.CL8MSWIN1251.
  6. Нажмите «ОК» во всех открытых окнах для сохранения изменений.

КРИТИЧЕСКИ ВАЖНО: Если код подключения к Oracle выполняется на стороне сервера 1С (например, в фоновом задании или в серверном модуле), изменения в системных переменных среды не вступят в силу автоматически! Служба сервера 1С («1С:Предприятие 8.3 Сервер») кэширует переменные окружения при своем запуске. Вам необходимо полностью перезапустить службу srv1cv83 (ragent) через оснастку services.msc, иначе 1С продолжит считывать старое окружение, и знаки вопроса не исчезнут.

Решение 2. Корректировка реестра Windows для клиента Oracle

Если вы не хотите создавать глобальную системную переменную окружения, можно настроить параметр локально для конкретного установленного клиента Oracle через системный реестр Windows.

Здесь важно учитывать разрядность операционной системы, разрядность платформы 1С и разрядность установленного клиента Oracle. Разберем два сценария:

Сценарий А: 64-битный сервер 1С и 64-битный клиент Oracle

Откройте редактор реестра regedit и перейдите по следующему пути:

HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_[Имя_Вашего_Окружения_Oracle]

Найдите параметр с именем NLS_LANG и установите его значение в AMERICAN_AMERICA.CL8MSWIN1251.

Сценарий Б: 32-битный клиент Oracle на 64-битной Windows

Если у вас используется 32-битный сервер 1С (или вы запускаете толстого/тонкого клиента в 32-битной версии), то 32-битный драйвер Oracle обращается к другой ветке реестра:

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\ORACLE\KEY_[Имя_Вашего_Окружения_Oracle]

Точно так же измените значение строкового параметра NLS_LANG на AMERICAN_AMERICA.CL8MSWIN1251.

Примечание: Системная переменная среды (Решение 1) всегда имеет более высокий приоритет, чем настройки реестра (Решение 2). Если задана системная переменная, Oracle проигнорирует настройки реестра.

Решение 3. Переход со старого ODBC на производительный OLE DB

В исходном коде для связи с СУБД использовался ODBC-драйвер: Driver={Oracle in OraDb12g_home1}. Этот подход имеет ряд ограничений в современных информационных системах на базе 1С. Более надежным, современным и производительным решением является использование нативного OLE DB провайдера от Oracle — OraOLEDB.Oracle.

Преимущества перехода на OLE DB:

Проанализируем пример кода с использованием OLE DB провайдера, который решает проблему с кодировкой и упрощает администрирование:


Соединение = Новый COMОбъект("ADODB.Connection");

// Формируем строку подключения по технологии TNS-less без использования tnsnames.ora
СтрокаПодключения = "Provider=OraOLEDB.Oracle;" +
                     "Data Source=(DESCRIPTION=" +
                     "(ADDRESS=(PROTOCOL=TCP)(HOST=" + ИмяСервера + ")(PORT=" + Порт + "))" +
                     "(CONNECT_DATA=(SERVICE_NAME=" + ИмяСлужбы + ")));" +
                     "User Id=" + Логин + ";" +
                     "Password=" + Пароль + ";";

Соединение.ConnectionString = СтрокаПодключения;
Соединение.Open();

ТекстЗапроса = " 
|SELECT 
| zpu_name AS ""Name"" 
|FROM PARUS.ZPU_TYPES"; 

rsRES = Новый COMОбъект("ADODB.Recordset"); 
rsRES.Open(ТекстЗапроса, Соединение); 

Пока rsRES.EOF() = 0 Цикл 
    Имя = СокрЛП(rsRES.Fields("Name").Value); 
    Сообщить(Имя); 
    rsRES.MoveNext(); 
КонецЦикла;

rsRES.Close();
Соединение.Close();

Решение 4. Настройка кодировки, если сервер 1С работает под управлением Linux

В последние годы многие компании переводят серверную инфраструктуру 1С на операционную систему Linux. Если сервер 1С работает под Linux и обращается к внешней базе данных Oracle, настройки реестра Windows окажутся абсолютно нерелевантными.

В Linux-среде необходимо передать переменную окружения NLS_LANG непосредственно процессу службы сервера 1С. Сделать это можно следующими способами:

  1. Если запуск сервера 1С настроен через классический конфигурационный файл инициализации (например, в ОС Ubuntu/Debian/CentOS это файл /etc/default/srv1cv83), добавьте в конец файла строку:

    export NLS_LANG=AMERICAN_AMERICA.AL32UTF8

  2. Если служба запускается через систему управления системными службами systemd, необходимо отредактировать юнит-файл службы (обычно это srv1cv83.service). Добавьте директиву Environment в секцию [Service]:

    [Service]
    Environment="NLS_LANG=AMERICAN_AMERICA.AL32UTF8"

Важное отличие кодировок для Linux: Обратите внимание, что для Linux-окружения в качестве кодовой страницы клиента рекомендуется указывать современный стандарт AL32UTF8 (UTF-8) вместо устаревшего Windows-1251 (CL8MSWIN1251). Платформа 1С на Linux нативно работает с кодировкой UTF-8, что полностью исключает искажение символов.

Решение 5. Локальный обход проблемы в SQL-запросе (если нет прав администратора)

Бывают ситуации, когда у разработчика 1С нет административных прав на сервере приложений 1С или СУБД Oracle для изменения системных переменных окружения или реестра Windows. В этом случае проблему со знаками вопроса можно обойти программным путем на уровне сессии базы данных или самого SQL-запроса.

Вариант А. Настройка языковых параметров сессии

Сразу после открытия ADO-соединения можно принудительно выполнить команды инициализации языковых параметров для конкретной открытой сессии подключения:


Соединение.Open();
// Управляем языком возвращаемых сообщений об ошибках и датами
Соединение.Execute("ALTER SESSION SET NLS_LANGUAGE = 'AMERICAN'");
Соединение.Execute("ALTER SESSION SET NLS_TERRITORY = 'AMERICA'");

Важное ограничение: Команды ALTER SESSION позволяют переопределить формат вывода дат, чисел и язык системных ошибок, но саму кодовую страницу (например, CL8MSWIN1251) изменить в уже открытой сессии СУБД не позволит, так как она жестко инициализируется клиентским драйвером на этапе рукопожатия (handshake) при подключении.

Вариант Б. Принудительное перекодирование функцией CONVERT в SQL

Если кодовая страница базы данных известна (например, данные в таблицах хранятся в формате UTF-8), мы можем заставить саму СУБД Oracle на своей стороне на лету перекодировать текст в нужный нам формат перед тем, как отдать его в ADO-рекордсет 1С. Для этого используется встроенная функция Oracle SQL — CONVERT.

Изменим запрос автора из примера следующим образом:


ТекстЗапроса = " 
|SELECT 
| CONVERT(zpu_name, 'CL8MSWIN1251', 'AL32UTF8') AS ""Name"" 
|FROM PARUS.ZPU_TYPES";

Параметры функции CONVERT(string, dest_char_set, [source_char_set]) означают:

Этот способ позволяет гарантированно получить читаемый русский текст без внесения каких-либо настроек в реестр или системные переменные операционной системы Windows / Linux.

Резюме и рекомендации

Мы проанализировали причины искажения кириллицы при интеграции 1С и Oracle. Для предотвращения появления знаков вопроса придерживайтесь следующих правил:

← На главную