Назад | Перейти на главную страницу

Как заставить беса использовать правильный набор символов?

Я пытаюсь импортировать файл dmp из одной базы данных в другую. Проблема в том, что некоторые специальные датские символы не импортируются правильно, потому что во время импорта выполняется некоторое преобразование карты символов.

Это информация, когда я запускаю импорт с помощью imp (см. Примечание о возможном преобразовании символов):

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

Export file created by EXPORT:V10.02.01 via conventional path

import done in WE8ISO8859P1 character set and AL16UTF16 NCHAR character set
import server uses AL32UTF8 character set (possible charset conversion)
. importing USERNAME's objects into USERNAME    
. . importing table                      "TABLE2" 
IMP-00019: row rejected due to ORACLE error 12899
IMP-00003: ORACLE error 12899 encountered
ORA-12899: værdi er for stor for kolonnen "USERNAME"."TABLE2"."NAME" (faktisk: 32, maksimum: 30)
Column 1 408261
Column 2 KUBEN FÆLLES MÅLER            

Каждый специальный символ (обычно Æ, Ø и Å) использует 2 символа вместо 1, а данные дополняются пробелами для заполнения, поэтому это вызывает ошибку, заключающуюся в том, что данные содержат 31 символ для этого поля, и поле определено как размер 30.

Экспорт, сгенерировавший файл dmp, выполнялся следующим образом:

SET CHARACTERSET=WE8PC850
SET NLS_LANG=DANISH
SET NLS_NUMERIC_CHARACTERS=.,
exp username/password@server1 dumpfile.dmp

Импорт был выполнен следующим образом: Как мне заставить это работать правильно?

SET CHARACTERSET=WE8PC850
SET NLS_LANG=DANISH
SET NLS_NUMERIC_CHARACTERS=.,
imp username/password@server2 fromuser=username touser=username commit=y ignore=y file=dumpfile.dmp log=dumpfile.log

Что можно сделать, чтобы это исправить? Похоже, что imp игнорирует используемую кодировку, поскольку сервер импорта использует AL32UTF8 (что неверно).

Вы импортируете данные в базу данных, используя набор символов AL32UTF8 (это значение по умолчанию). Поэтому импортер должен преобразовать символы, чтобы они соответствовали этому, и некоторые из них станут многобайтовыми символами, как вы обнаружили. Есть два способа справиться с этим:

1) Если вам не нужен Unicode в новой базе данных, воссоздайте его с тем же набором символов, что и в старой базе данных. Запустите этот код в старой базе данных, чтобы получить набор символов и использовать его

SELECT parameter, value
FROM nls_database_parameters
WHERE parameter
LIKE '%CHARACTERSET';

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

2) Если вы можете заранее создать таблицы, вы можете использовать NLS_LENGTH_SEMANTICS параметр. Если вы установите для него значение CHAR, а не значение по умолчанию BYTE, для VARCHAR2 (5) будет выделено достаточно места для хранения 5 символов в наборе символов базы данных (потенциально до 20 байтов), а не 5 байтов (что может позволить только 1 символ ). Или вместо этого вы можете изменить DDL создания таблицы, чтобы добавить CHAR в каждое объявление столбца VARCHAR2. например

CREATE TABLE xyz (column_x VARCHAR2(10 CHAR) NOT NULL);

Таким образом вы можете преобразовать данные в Unicode и получить лучший набор символов в будущем, и пока ваше приложение может его поддерживать, это, возможно, предпочтительный метод.

Мы решили эту проблему, изменив все символьные поля для использования CHAR вместо значения по умолчанию BYTE. Это в основном вариант 2, предложенный @BrokenCrust в его ответ. Вместо того, чтобы заново создавать таблицы, мы просто переопределили их с помощью этого SQL:

set head off;
set linesize 1000;
set colsep ";";
set trimspool on;
set pagesize 0;
set verify off;
set feedback off;
set term off;
column dcol new_value mydate noprint;
select to_char(sysdate,'YYYY-MM-DD_HH24MISS') dcol from dual;
select to_char(sysdate,'YYYY-MM-DD') dcol from dual;
spool c:\temp\From_Byte_to_Char_og_VarChar2&mydate;
select '-- '||sysdate from dual;
select 'ALTER TABLE '||TABLE_NAME||
      ' MODIFY '||COLUMN_NAME||' CHAR('||data_length||' CHAR);' 
from 
     user_tab_cols
where 
     DATA_TYPE='CHAR'
;
select 'ALTER TABLE '||TABLE_NAME||
      ' MODIFY '||COLUMN_NAME||' VARCHAR2('||data_length||' CHAR);' 
from 
     user_tab_cols
where 
     DATA_TYPE='VARCHAR2'
;
select 'commit ;' from dual;
select 'exit ;' from dual;
spool off ;

если вы используете сервер Oracle XE, невозможно изменить кодировку сервера базы данных или любой другой базы данных. Я тоже ищу ответ.