В локальной сети предприятия есть два сервера. На первом сервере установлен Red Hat Enterprise Linux AS release 3 (Taroon Update 5). Кроме того на первом сервере установлен Oracle9i Enterprise Edition Release 9.2.0.7.0 - 64bit Production (в дальнейшем по тексту я буду называть этот сервер источником данных). В локалях сервера кодировка UTF-8.
Кодировка в Oracle CL8MSWIN1251
На втором сервере (в дальнейшем по тексту сервер приемник данных) установлена операционная система CentOS Linux release 6.0 (Final). В качестве СУБД установлен PostgreSQL 8.4.4. В локалях сервера кодировка UTF-8.
В качестве кодировки в БД в postgreSQL выбрана ru_RU.UTF-8.
Между БД приемником и БД исочником организована связь при помощи unixODBC 2.2.14.
Делаю выборку данных при помощи следующих 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.
Что необходимо сделать, чтобы русские символы при выборке по ODBC-Link отображались корректно ?
Привести кодировку к одной. Сами же пишите в Oracle - windows-1251, а в PostgreSQL - UTF-8.
Попробуйте переключить кодировку в PostgreSQL через 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 не удалось.
В ходе поиска решения было замечено что на символ знак вопроса заменяются только буквы русского языка т.е. цифровые значения по dblink передаются корректно поэтому было принято решение передавать тестовые данные по dblink при помощи кодов символов в кодировке Utf-8. Для этого в СУБД под управление Oracle была написана процедура в результате ее работы строка переданная ей в качестве входного параметра преобразуется в в строку из кодов символов в кодировке utf-8 записанные через разделитель "^". Далее строка безошибочно передается по dblink т.к. не содержит русских букв и только после этого в СУБД под управлением postgre коды символов преобразуются сново в символы в соотсвествии с кодировкой Utf-8. Я понимаю что описанное мной решение не является идеальным т.к. существуют затраты времени на перекодирование строки, но на данный момент я избавиться от этих потерь времени не могу.
Привести кодировку к одной.
Привести кодировку к одной. Сами же пишите в Oracle - windows-1251, а в PostgreSQL - UTF-8.
Попробуйте переключить кодировку в PostgreSQL через SET CLIENT_ENCODING TO...
В окне терминала на сервере
В окне терминала на сервере приемнике данных ввел команду set CLIENT_ENCODING to win1251. Проверил что локали установились в ru_RU.WINDOWS-1251.
В этом же окне терминала подключился к БД приемнику командой psql <Имя БД приемника>.
Ввел пароль, установил связи по ODBC-Link:
Сделал выборку данных командой:
Русские символы также как и до 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 не удалось.
В ходе поиска решения было замечено что на символ знак вопроса заменяются только буквы русского языка т.е. цифровые значения по dblink передаются корректно поэтому было принято решение передавать тестовые данные по dblink при помощи кодов символов в кодировке Utf-8. Для этого в СУБД под управление Oracle была написана процедура в результате ее работы строка переданная ей в качестве входного параметра преобразуется в в строку из кодов символов в кодировке utf-8 записанные через разделитель "^". Далее строка безошибочно передается по dblink т.к. не содержит русских букв и только после этого в СУБД под управлением postgre коды символов преобразуются сново в символы в соотсвествии с кодировкой Utf-8. Я понимаю что описанное мной решение не является идеальным т.к. существуют затраты времени на перекодирование строки, но на данный момент я избавиться от этих потерь времени не могу.