Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2885780
  • 博文数量: 599
  • 博客积分: 16398
  • 博客等级: 上将
  • 技术积分: 6875
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-30 12:04
个人简介

WINDOWS下的程序员出身,偶尔也写一些linux平台下小程序, 后转行数据库行业,专注于ORACLE和DB2的运维和优化。 同时也是ios移动开发者。欢迎志同道合的朋友一起研究技术。 数据库技术交流群:58308065,23618606

文章分类

全部博文(599)

文章存档

2014年(12)

2013年(56)

2012年(199)

2011年(105)

2010年(128)

2009年(99)

分类: Oracle

2012-06-26 10:38:21

在数据库迁移过程中,需要考虑源库和目标库字符集。
如果从GBK迁移到UTF8中,遇到多字符的问题很有可能导致ORA-12899错误。
如下一个简单的例子可以演示:

源库 WINDOWS机器上的ORACLE 10.2.0.1 ,字符集是ZHS16GBK。
SQL> SELECT * FROM V$VERSION;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE    10.2.0.1.0      Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production
SQL> SELECT VALUE$ FROM PROPS$
  2  WHERE NAME='NLS_CHARACTERSET';
VALUE$
--------------------
ZHS16GBK
SQL>

目标库是AIX平台上的Oracle10.2.0.4 字符集是AL32UTF8
SQL> SELECT * FROM V$VERSION;
BANNER
--------------------------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
PL/SQL Release 10.2.0.4.0 - Production
CORE    10.2.0.4.0      Production
TNS for IBM/AIX RISC System/6000: Version 10.2.0.4.0 - Productio
NLSRTL Version 10.2.0.4.0 - Production
SQL> SELECT VALUE$ FROM PROPS$
  2  WHERE NAME='NLS_CHARACTERSET';
VALUE$
--------------------------------------------------------------------------------
AL32UTF8
SQL>

在源库中创建测试表:
 
SQL> CREATE TABLE TEST(ID INT,NAME VARCHAR2(8));
表已创建。
SQL> INSERT INTO TEST VALUES(1,'中国');
已创建 1 行。
SQL> COMMIT;
提交完成。
SQL> SELECT * FROM TEST;
        ID NAME
---------- --------------------
         1 中国

SQL> host exp test/test file=test.dmp tables=test
Export: Release 10.2.0.1.0 - Production on 星期二 6月 26 10:28:29 2012
Copyright (c) 1982, 2005, Oracle.  All rights reserved.

连接到: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
已导出 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集
即将导出指定的表通过常规路径...
. . 正在导出表                            TEST导出了           1 行
成功终止导出, 没有出现警告。

SQL> host imp file=test.dmp  fromuser=test touser=scott
Import: Release 10.2.0.1.0 - Production on 星期二 6月 26 10:29:47 2012
Copyright (c) 1982, 2005, Oracle.  All rights reserved.

连接到: Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Produc
tion
With the Partitioning, Real Application Clusters, OLAP, Data Mining
and Real Application Testing options
经由常规路径由 EXPORT:V10.02.01 创建的导出文件
警告: 这些对象由 TEST 导出, 而不是当前用户
已经完成 ZHS16GBK 字符集和 UTF8 NCHAR 字符集中的导入
导入服务器使用 AL32UTF8 字符集 (可能的字符集转换)
导出服务器使用 AL16UTF16 NCHAR 字符集 (可能的 ncharset 转换)
. 正在将 TEST 的对象导入到 SCOTT
. . 正在导入表                          "TEST"导入了           1 行
成功终止导入, 没有出现警告。
 

SQL> SHOW USER
USER 为 "SCOTT"
SQL> SELECT * FROM SCOTT.TEST;
        ID NAME
---------- ----------------
         1 中国
SQL>

可以看到数据可以正常导入。
 
下面我们简单在源库做一下数据的修改:

SQL> SELECT * FROM TEST;
        ID NAME
---------- --------------------
         1 中国
SQL> UPDATE TEST SET NAME='中国人';
已更新 1 行。
SQL> COMMIT;
提交完成。
SQL> SELECT * FROM TEST;
        ID NAME
---------- --------------------
         1 中国人
SQL> host exp test/test file=test.dmp tables=test
Export: Release 10.2.0.1.0 - Production on 星期二 6月 26 10:32:25 2012
Copyright (c) 1982, 2005, Oracle.  All rights reserved.

连接到: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
已导出 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集
即将导出指定的表通过常规路径...
. . 正在导出表                            TEST导出了           1 行
成功终止导出, 没有出现警告。
SQL> host imp file=test.dmp  fromuser=test touser=
scott ignore=yes
Import: Release 10.2.0.1.0 - Production on 星期二 6月 26 10:32:43 2012
Copyright (c) 1982, 2005, Oracle.  All rights reserved.

连接到: Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Produc
tion
With the Partitioning, Real Application Clusters, OLAP, Data Mining
and Real Application Testing options
经由常规路径由 EXPORT:V10.02.01 创建的导出文件
警告: 这些对象由 TEST 导出, 而不是当前用户
已经完成 ZHS16GBK 字符集和 UTF8 NCHAR 字符集中的导入
导入服务器使用 AL32UTF8 字符集 (可能的字符集转换)
导出服务器使用 AL16UTF16 NCHAR 字符集 (可能的 ncharset 转换)
. 正在将 TEST 的对象导入到 SCOTT
. . 正在导入表                          "TEST"
IMP-00019: 由于 ORACLE 错误 12899 而拒绝行
IMP-00003: 遇到 ORACLE 错误 12899
ORA-12899: 列 "SCOTT"."TEST"."NAME" 的值太大 (实际值: 9, 最大值: 8)
列 1 1
列 2 中国人导入了           0 行
成功终止导入, 但出现警告。
SQL>

可以看到这次报错了,列的值太大。
在GBK下,一个汉字占2个字节。

SQL> SELECT DUMP('中国人',1016) FROM DUAL;
DUMP('中国人',1016)
-----------------------------------------------------
Typ=96 Len=6 CharacterSet=ZHS16GBK: d6,d0,b9,fa,c8,cb

在UTF8下,一个汉字占3个字节。
SQL> SELECT DUMP('中国人',1016) FROM DUAL;
DUMP('中国人',1016)
-----------------------------------------------------------------------------
Typ=96 Len=9 CharacterSet=AL32UTF8: e4,b8,ad,e5,9b,bd,e4,ba,ba

而表的定义为VARCHAR2(8)

SQL> DESC TEST.TEST
 名称                                      是否为空? 类型
 ----------------------------------------- -------- ------------------------
 ID                                                 NUMBER(38)
 NAME                                               VARCHAR2(8)
 
VARCHAR2(8)在GBK下可以存放4个汉字,而在UTF8下只能存放2个汉字。
 
遇到这种情况,可以提前把表建立,修改列的长度然后在导入。
 
阅读(4502) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~