![我如何让 imp 使用正确的字符集?](https://linux22.com/image/563176/%E6%88%91%E5%A6%82%E4%BD%95%E8%AE%A9%20imp%20%E4%BD%BF%E7%94%A8%E6%AD%A3%E7%A1%AE%E7%9A%84%E5%AD%97%E7%AC%A6%E9%9B%86%EF%BC%9F.png)
我正在尝试将 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(这是错误的)。
答案1
您正在使用 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,并获得更好的字符集,只要您的应用程序可以支持它,这也许是首选方法。
答案2
我们最终通过将所有字符字段更改为使用CHAR
而不是默认的来解决这个问题BYTE
。这基本上是@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 ;
答案3
如果您使用的是 Oracle Server XE,则无法更改数据库服务器或任何数据库的字符集。我也在寻找答案。