Почему Char(1) меняется на Char(3) при копировании по Oracle DBLINK?

У меня есть 2 базы данных, и я хочу перенести существующую таблицу, содержащую столбец CHAR, из базы данных A в базу данных B.

База данных A — это Oracle 9i, имеет кодировку WE8ISO8859P1 и содержит таблицу «foo», по крайней мере, с 1 столбцом типа CHAR (1 char). Я не могу изменить таблицу в базе данных A, поскольку она является частью сторонней установки.

База данных B — это моя собственная база данных Oracle 10g, использующая кодировку AL32UTF8 по разным причинам, и я хочу скопировать foo в эту базу данных.

Я устанавливаю ссылку базы данных из базы данных B в базу данных A. Затем я выполняю следующую команду:

*создать панель таблицы как select * from #link#.foo;*

Данные хорошо копируются, но когда я проверяю типы столбцов, я замечаю, что CHAR (1 символ) был преобразован в CHAR (3 символа), а при запросе данных в базе данных B все дополняется пробелами. .

Я думаю, что где-то под водой Oracle путает свои собственные байты и символы. CHAR(1 байт) отличается от CHAR(1 char) и т.д. Я читал обо всем этом.

Почему тип данных изменяется на дополненный CHAR (3 символа) и как мне запретить Oracle делать это?

Правка: похоже, это связано с переносом символов CHAR между двумя определенными уровнями исправлений Oracle 9 и 10. Похоже, это действительно ошибка. как только узнаю, выложу обновление. Между тем: не пытайтесь перемещать CHAR между базами данных, как я описал. VARCHAR2 работает нормально (проверено).

Изменить 2: Я нашел ответ и разместил его здесь: Почему Char(1) меняется на Char(3) при копировании через Oracle DBLINK? Жаль, что я не могу принять свой собственный ответ, потому что моя проблема решена.


person Rolf    schedule 31.10.2008    source источник


Ответы (3)


Эта проблема вызвана тем, как Oracle (неправильно) обрабатывает преобразования символов между различными наборами символов на основе исходного определения длины столбца. Когда вы определяете размер столбца символьного типа в байтах, Oracle не знает, как выполнить преобразование, и искажает его. Решение состоит в том, чтобы всегда определять длину символьного типа в символах.

Для более подробного объяснения проблемы и того, как я это понял, посмотрите http://www.rolfje.com/2008/11/04/transporting-oracle-chars-over-a-dblink/

person Rolf    schedule 04.11.2008

Вам необходимо изучить разницу между NLS WE8ISO8859P1 (который хранит символы в одном байте) и AL32UTF8, который хранит символы до четырех байтов. Вам нужно будет потратить некоторое время на поддержку национальных языков Oracle (NLS) Документация. Oracle автоматически выполняет преобразование через ссылку на базу данных, пытаясь быть полезным.

Попробуйте следующее из приглашения SQL:

ALTER SESSION NLS_NCHAR WE8ISO8859P1 
create table bar as select * from #link#.foo;
person Thomas Jones-Low    schedule 31.10.2008
comment
Yeh NLS это боль. Бьюсь об заклад, у вас была своя доля тихих вечеров с документами. ;-) - person ; 31.10.2008
comment
Я бы понял, если бы исходный тип был 1 символ, а он был изменен на 3 байта или 4 байта. Почему 1 символ был изменен на 3 символа? - person Dave Costa; 31.10.2008
comment
Я читаю об этом уже 32 часа. Так что я согласен с Дейвом, 1 символ -> 3 байта, я понимаю. Но 1 символ -> 3 символа и добавление отступов совершенно неправильно. Если бы я установил NLS_NCHAR, я бы установил NLS локальной базы данных. Вместо этого вы решили установить удаленный NLS. Почему? - person Rolf; 31.10.2008
comment
Забавное дополнение: установка NLS_CHAR в сеансе через jdbc почему-то невозможна. Я пробовал NLS_CHAR в SquirrelSQL, но безрезультатно. Я считаю онлайн-документацию Oracle одним большим лабиринтом перекрестных ссылок, который не содержит ясного и полезного текста. - person Rolf; 02.11.2008

Первое, что я бы попробовал, это создать таблицу НЕ как CTAS, но со списком определений столбцов и попытаться выполнить вставку первых нескольких тысяч строк. Если бы это не удалось, тогда было бы очень ясно, почему... и вы бы получили быстрое подтверждение того, что Томас Лоу абсолютно точен.

person Community    schedule 31.10.2008