我想从一个数据库导入一个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字符集将数据导入数据库(这是默认设置)。 因此,导入程序必须将字符转换为适合的字符,并且一些字符将变成您find的多字节字符。 有两种方法可以解决这个问题:
1)如果在新数据库中不需要Unicode,则使用与旧数据库相同的字符集重新创build它。 在旧数据库上运行此代码以获取字符集并使用它
SELECT parameter, value FROM nls_database_parameters WHERE parameter LIKE '%CHARACTERSET';
一旦新旧数据库具有相同的字符集,导入就不必进行转换。
2)如果可以预先创build表,则可以使用NLS_LENGTH_SEMANTICS参数。 如果将其设置为CHAR而不是BYTE的默认值,则将为VARCHAR2(5)分配足够的空间,以便在数据库字符集中存储5个字符(可能高达20个字节),而不是5个字节(这可能只允许1个字符)。 或者您也可以修改表创buildDDL以将CHAR添加到每个VARCHAR2列声明。 例如
CREATE TABLE xyz (column_x VARCHAR2(10 CHAR) NOT NULL);
这样,你可以将数据转换为Unicode,并有更好的字符集,只要你的应用程序可以支持它,这也许是首选的方法。
如果您使用的是Oracle服务器XE,则无法更改数据库服务器或任何数据库的字符集。 我也在寻找答案。
我们最终通过将所有字符字段更改为使用CHAR而不是缺省BYTE来解决此问题。 这基本上是@BrokenCrust在他的回答中提出的选项2。 我们不是重新创build表格,而是使用这个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 ;