问题简要如题目所示,详情如下:
① 首先介绍背景:
由于我们项目组A,的开发需要基于另有一个公司P 的的数据库工作。于是我们拿他们导出来的数据作为临时开发用。
② 过程:
P将他们的数据库导出为 ppp.dmp 文件 (
从我imp时 的日志看,应该是用system用户导出的,所以应该是导出了整个实例;
查看过他们的数据库字符集:
NLS_CHARACTERSET AL32UTF8
NLS_NCHAR_CHARACTERSET AL16UTF16
)
然后,我们向我们本地的数据库导入:
(第一回),我用的之前创建好的数据库实例,查到字符集是:
NLS_CHARACTERSET ZHS16GBK
NLS_NCHAR_CHARACTERSET AL16UTF16
创建好对应的用户、表空间就开始导入录入了;
还是那些命令:
imp system/system@localhost/orcl file=ppp.dmp log=ppp.log full=y buffer=80多少忘了00 ;
除报一些用户不存在、一些ALB 已存在之类的警告外。一切顺利。
但是,当我在用kettle将orcl下用户user1的所有表包括的数据向orcl下的用户usertmp转移的时候。个别表出现了这样这样的问题:
ORA-12899: 列XXX的值太大 (实际值: 126, 最大值: 100)之类的语句
(第二回),我新建了一个实例,并且默认字符集为 AL32UTF8,建好用户、表空间,导入。以下是截取的一部分导入日志:
经由常规路径由 EXPORT:V11.02.00 创建的导出文件
已经完成 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集中的导入
导入服务器使用 AL32UTF8 字符集 (可能的字符集转换)
导出客户机使用 US7ASCII 字符集 (可能的字符集转换)
. 正在将 SYSTEM 的对象导入到 SYSTEM
. 正在将 WHSCJG 的对象导入到 。。。
。。。
. . 正在导入表 "EISS_TAB_USER"
IMP-00019: 由于 ORACLE 错误 12899 而拒绝行
IMP-00003: 遇到 ORACLE 错误 12899
ORA-12899: 列 "WHSCJG"."EISS_TAB_USER"."U_USERID" 的值太大 (实际值: 39, 最大值: 32)
列 1 134851
列 2 138255
列 3 system
列 4 聚集区管理员
列 5 ZwsUcorZkCrsujLiL6T2vQ==
...
③ 个别线索:
本地原先的那个实例,好像有过更改字符集的经历,但是具体以何种方式,当事人已忘记了;
第一次导入后,查看表、字段的注释,其中的汉字都是问号;
在另一台笔记本的oracle(32位)服务上尝试导入。成功没有, ORA-12899:这种问题。
//======================================================================
不知哪位大牛有相关经验,望深入将建其中机理,指点迷经。万分感激
------解决方案--------------------
看来主要是字符集的问题引起的
导入时可以值关注有意义的用户,不必把整个数据库都导进去
字符集的问题主要有四个方面
1、远端数据库字符集
2、导出远端客户端字符集
3、导入目的端客户端字符集
4、导入目的端数据库字符集
这些地方的字符集应相同或兼容,最好相同
------解决方案--------------------
感觉应该是和更改字符集有关
使用中的数据库更改字符集,对已经存在数据库中的数据是没影响的
更改之前的数据应该还是按原来的字符集进行存储
导出再导入会把原字符集的数据转化为新字符集,从而导致字段长度变化
建议将报错的数据表字段增大,如果仅作为开发、测试使用,应该没啥影响
------解决方案--------------------
导出客户机使用 US7ASCII 字符集 (可能的字符集转换)
exp导出时最好在使用的客户端也设置好字符集
可以使用expdp/impdp来导,跳过字符集的问题
------解决方案--------------------
如果用al32utf8,可以分两次imp,第一次导入表结构,然后写个存储过程将字符型的字段的长度加长
第二次导入数据
但是有个问题,你的数据可能在exp导出的时候已经发生了字符集转换,不小心已经存在了乱码。还不如重新导出导入一遍。数据量大的话,数据泵的优势更明显
或者用gbk字符集确定没有问题的话,就用这个实例好了,没必要再重新导到al32utf8下,user1往usertmp转移数据报错,应该检查两边的表的相关字段定义的长度是不是不一致。指定导入某个用户的数据,在imp中指定参数fromuser和touser即可
------解决方案--------------------
varchar2(10)=varchar2(10 byte)
和varchar2(10 char)是不一样的
比如在GBK字符集下,一个汉字占2个字节。一个“一二三四五六”在user1中能正常插入,应为6个字符小于10个字符的限制,在usertmp中就会报错,因为6个汉字占12个字节,超过了10个字节的限制