Проблемы с кодировкой по ODBC-Link

В локальной сети предприятия есть два сервера. На первом сервере установлен Red Hat Enterprise Linux AS release 3 (Taroon Update 5). Кроме того на первом сервере установлен Oracle9i Enterprise Edition Release 9.2.0.7.0 - 64bit Production (в дальнейшем по тексту я буду называть этот сервер источником данных). В локалях сервера кодировка UTF-8.

Используйте данную ссылку, что бы развернуть или свернуть блок текста

Результат выполнения команды locale на сервере источнике данных:
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=


Кодировка в Oracle CL8MSWIN1251
Используйте данную ссылку, что бы развернуть или свернуть блок текста

Результат выполнения запроса (SELECT * FROM NLS_DATABASE_PARAMETERS;) по выборке кодировки в Oracle:
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTERS .,
NLS_CHARACTERSET CL8MSWIN1251

На втором сервере (в дальнейшем по тексту сервер приемник данных) установлена операционная система CentOS Linux release 6.0 (Final). В качестве СУБД установлен PostgreSQL 8.4.4. В локалях сервера кодировка UTF-8.
Используйте данную ссылку, что бы развернуть или свернуть блок текста

Результат выполнения команды locale на сервере приемнике данных:
LANG=ru_RU.UTF-8
LC_CTYPE="ru_RU.UTF-8"
LC_NUMERIC="ru_RU.UTF-8"
LC_TIME="ru_RU.UTF-8"
LC_COLLATE="ru_RU.UTF-8"
LC_MONETARY="ru_RU.UTF-8"
LC_MESSAGES="ru_RU.UTF-8"
LC_PAPER="ru_RU.UTF-8"
LC_NAME="ru_RU.UTF-8"
LC_ADDRESS="ru_RU.UTF-8"
LC_TELEPHONE="ru_RU.UTF-8"
LC_MEASUREMENT="ru_RU.UTF-8"
LC_IDENTIFICATION="ru_RU.UTF-8"
LC_ALL=


В качестве кодировки в БД в postgreSQL выбрана ru_RU.UTF-8.
Используйте данную ссылку, что бы развернуть или свернуть блок текста

Данные из окна просмотра сведений о БД в web-интерфейсе:
База данных Пользователь Кодировка Collation Character Type
CAT postgres UTF8 ru_RU.UTF-8 ru_RU.UTF-8

Между БД приемником и БД исочником организована связь при помощи unixODBC 2.2.14.
Используйте данную ссылку, что бы развернуть или свернуть блок текста

Файл настройки unixODBC /etc/odbc.ini:
[M3ATI]  
Description  = Oracle ODBC  
Driver   = M3ATI  
Trace   = yes  
TraceFile  = /tmp/odbc_oracle.log  
ServerName  = //<IP-адрес сервера источника>:<Порт>/<Имя БД>
DATABASE = <Имя БД>
UserID   = <Имя пользователя> 
Password  = <Пароль>
Port   = <Порт>

Файл настройки unixODBC /etc//etc/odbcinst.ini :
[M3ATI] 
Description = Oracle ODBC Connection Driver  
Driver  = /usr/lib64/libsqora.so.10.1  
Driver64  = /usr/lib64/libsqora.so.10.1  
Debug  = 0  
CommLog  = 1 


Делаю выборку данных при помощи следующих SQL-команд:
SELECT odbclink.connect('DSN=M3ATI');
SELECT * FROM odbclink.query(1,'SELECT id,name,description from repl_db.links') AS t (id numeric,name text,description text);

в результате выполнения sql русские символы в полях БД источника заменяются на символ знак вопроса ("????"). Попытке выборки проводились как из программы администрирования БД (PgAdmin III 1.14.0) так и из утилиты psql.
Используйте данную ссылку, что бы развернуть или свернуть блок текста

Результат выполнения запроса по выборке данных из БД источника:
id numeric name text description text
2 POL ??? ?????? ??????????? ????????? ???????????

Что необходимо сделать, чтобы русские символы при выборке по ODBC-Link отображались корректно ?

Опции просмотра комментариев

Выберите предпочитаемый вами способ показа комментариев и нажмите "Сохранить настройки" для активации изменений.

Привести кодировку к одной.

Привести кодировку к одной. Сами же пишите в Oracle - windows-1251, а в PostgreSQL - UTF-8.
Попробуйте переключить кодировку в PostgreSQL через SET CLIENT_ENCODING TO...

В окне терминала на сервере

В окне терминала на сервере приемнике данных ввел команду set CLIENT_ENCODING to win1251. Проверил что локали установились в ru_RU.WINDOWS-1251.

Используйте данную ссылку, что бы развернуть или свернуть блок текста

locale: Cannot SET LC_CTYPE TO DEFAULT locale: No such file OR directory
locale: Cannot SET LC_MESSAGES TO DEFAULT locale: No such file OR directory
locale: Cannot SET LC_ALL TO DEFAULT locale: No such file OR directory
LANG=ru_RU.WINDOWS-1251
LC_CTYPE="ru_RU.WINDOWS-1251"
LC_NUMERIC="ru_RU.WINDOWS-1251"
LC_TIME="ru_RU.WINDOWS-1251"
LC_COLLATE="ru_RU.WINDOWS-1251"
LC_MONETARY="ru_RU.WINDOWS-1251"
LC_MESSAGES="ru_RU.WINDOWS-1251"
LC_PAPER="ru_RU.WINDOWS-1251"
LC_NAME="ru_RU.WINDOWS-1251"
LC_ADDRESS="ru_RU.WINDOWS-1251"
LC_TELEPHONE="ru_RU.WINDOWS-1251"
LC_MEASUREMENT="ru_RU.WINDOWS-1251"
LC_IDENTIFICATION="ru_RU.WINDOWS-1251"
LC_ALL=


В этом же окне терминала подключился к БД приемнику командой psql <Имя БД приемника>.
Ввел пароль, установил связи по ODBC-Link:
SELECT odbclink.connect('DSN=M3ATI');

Сделал выборку данных командой:
SELECT * FROM odbclink.query(1,'SELECT id,name,description from repl_db.links') AS t (id numeric,name text,description text);

Русские символы также как и до set CLIENT_ENCODING to ... заменяются на символ знак вопроса.

При чём здесь окно терминала

При чём здесь окно терминала и системная локаль?
set CLIENT_ENCODING to не меняет системную локаль и под неё и НЕ НУЖНО менять системную локаль. Данная команда лишь говорит серверу PostgreSQL, что на клиенте установлена такая-то кодировка и сервер должен отдавать данные в этой кодировке, транслируя в неё то, что реально лежит в базе. Сорри, я сперва не врубился в вашу схему, для которой set CLIENT_ENCODING to будет очевидно бесполезной, ведь Oracle об этом SET не имеет никакого понятия.

Если у вас ORACLE хранит данные в cp1251 то получается, что серверу, т.е. ORACLE нужно сказать, чтобы отдавал в UTF-8. Oracle плюёт на системную локаль с высокой башни - он всё хранит в себе. Как сказать Oracle чтобы он выдавал хранимые в cp1251 данные наружу в UTF-8, вопрос скорее к специалистам по Oracle.

Большое спасибо за подробные

Большое спасибо за подробные и оперативные ответы, я постараюсь поместить в эту ветку форума решение моей проблемы если мне удастся его найти.

Мое решение проблемы

Подобрать кодировки при которых dblink из postgesql в oracle заработал корректно мнe не удалось.

Используйте данную ссылку, что бы развернуть или свернуть блок текста
Вариант решения проблемы предложенный пользователем admin я также проверил. Для проверки в СУБД ORACLE было создано представление:
CREATE OR REPLACE VIEW REPL_DB.LINKS#S1
(ID, NAME, DESCRIPTION, DESC1)
AS 
SELECT 
id,CONVERT(name, 'CL8MSWIN1251', 'UTF8') name 
,CONVERT(description,'CL8MSWIN1251','US7ASCII') description 
,description desc1 
FROM repl_db.links 
UNION ALL 
SELECT 
id,CONVERT(name, 'CL8MSWIN1251', 'UTF8') name 
,CONVERT(description,'CL8MSWIN1251','WE8ISO8859P1') description 
,description desc1 
FROM repl_db.links 
UNION ALL 
SELECT 
id,CONVERT(name, 'CL8MSWIN1251', 'UTF8') name 
,CONVERT(description,'CL8MSWIN1251','EE8MSWIN1250') description 
,description desc1 
FROM repl_db.links 
UNION ALL 
SELECT 
id,CONVERT(name, 'CL8MSWIN1251', 'UTF8') name 
,CONVERT(description,'CL8MSWIN1251','WE8MSWIN1252') description 
,description desc1 
FROM repl_db.links 
UNION ALL 
SELECT 
id,CONVERT(name, 'CL8MSWIN1251', 'UTF8') name 
,CONVERT(description,'CL8MSWIN1251','WE8EBCDIC1047') description 
,description desc1 
FROM repl_db.links 
UNION ALL 
SELECT 
id,CONVERT(name, 'CL8MSWIN1251', 'UTF8') name 
,CONVERT(description,'CL8MSWIN1251','JA16SJISTILDE') description 
,description desc1 
FROM repl_db.links 
UNION ALL 
SELECT 
id,CONVERT(name, 'CL8MSWIN1251', 'UTF8') name 
,CONVERT(description,'CL8MSWIN1251','ZHT16MSWIN950') description 
,description desc1 
FROM repl_db.links 
UNION ALL 
SELECT 
id,CONVERT(name, 'CL8MSWIN1251', 'UTF8') name 
,CONVERT(description,'CL8MSWIN1251','UTF8') description 
,description desc1 
FROM repl_db.links 
UNION ALL 
SELECT 
id,CONVERT(name, 'CL8MSWIN1251', 'UTF8') name 
,CONVERT(description,'CL8MSWIN1251','AL32UTF8') description 
,description desc1 
FROM repl_db.links 
UNION ALL 
SELECT 
id,CONVERT(name, 'CL8MSWIN1251', 'UTF8') name 
,CONVERT(description,'CL8MSWIN1251','CL8MSWIN1251') description 
,description desc1 
FROM repl_db.links;

но при попытке выборки данных из него через dblink русские символы также заменяются на символ занк вопроса.

В ходе поиска решения было замечено что на символ знак вопроса заменяются только буквы русского языка т.е. цифровые значения по dblink передаются корректно поэтому было принято решение передавать тестовые данные по dblink при помощи кодов символов в кодировке Utf-8. Для этого в СУБД под управление Oracle была написана процедура в результате ее работы строка переданная ей в качестве входного параметра преобразуется в в строку из кодов символов в кодировке utf-8 записанные через разделитель "^". Далее строка безошибочно передается по dblink т.к. не содержит русских букв и только после этого в СУБД под управлением postgre коды символов преобразуются сново в символы в соотсвествии с кодировкой Utf-8. Я понимаю что описанное мной решение не является идеальным т.к. существуют затраты времени на перекодирование строки, но на данный момент я избавиться от этих потерь времени не могу.

Опции просмотра комментариев

Выберите предпочитаемый вами способ показа комментариев и нажмите "Сохранить настройки" для активации изменений.

Back to top

(С) Виктор Вислобоков, 2008-2023