以前也看了一些关于字符集转换的文章但是实际使用的时候还是发生了问题出现了乱码为了彻底搞清楚字符集问题我决定做测试用EXP/IMP工具在不同字符集之间互相转换数据 环境两台测试PC机器分称A机器()和B机器() 两台机器的配置都是一致的安装WIN操作系统和Oracle数据库 计划从A机器导出包含有中文的数据然后倒入到B机器中 测试计划 分别在两台机器上安装两个instance这两个instance又分别是中英文字符集 为了简单起见国家字符集和字符集设置都是一样的就是说设置成英文字符集的时候上面说的两个设置都是USASCII设置中文字符集的时候都是ZHSGBK我没有考虑国家字符集和字符集不一致的情况 客户端也分成CD两个部分实际测试的时候C和D是一个客户端因为如果A和C的字符集不一致是不允许导出的同样如果B和D的字符集不一致是不允许导入的 在C机器上建立四个服务指向上面新建的个instance c中文 在A机器上 e英文 在A机器上 c中文 在B机器上 e英文 在B机器上 四个进程都建立相同的用户和表 Connect system/manager Create user test identified by test default tablespace users temporary tablespace temp; Grant connectresource to test; Connect test/test Create table emp(id number() address varchar()); 然后只在A机器上的两个进程中插入数据 Insert into emp(idaddress) values(北京市); Insert into emp(idaddress) values(成都市); Insert into emp(idaddress) values(上海市); Insert into emp(idaddress) values(天津市); Insert into emp(idaddress) values(重庆市); Insert into emp(idaddress) values(武汉市); Insert into emp(idaddress) values(广州市); Commit; 然后测试过程如下 一在C机器上测试C机器是英文字符集 exp system/manager@c file=c:cdmp owner=test exp system/manager@e file=c:edmp owner=test 都导出成功 发现上面两个文件的ACSII字符集都是 二在C机器上测试C机器换成中文字符集 exp system/manager@c file=c:cdmp owner=test exp system/manager@e file=c:edmp owner=test 发现上面两个文件的ACSII字符集都是 A机器上的数据库变换字符集就是把原来英文字符集数据库换成中文字符集把原来中文字符集数据库换成英文字符集 备注之后没有把原来的数据删掉重新录入中文数据而是用以前的旧的数据后来发现原来英文字符集数据库换成中文字符集后数据可以正常显示反之中文字符集数据库换成英文字符集后数据已经是乱码了已经不能正常显示了 原因中文字符集占两个字节英文字符集占一个字节所以当中文转换成英文的时候数据库压缩数据就无法正常显示了反过来可以正常显示所以推荐建立数据库的时候用英文字符集好处多多(包括全文索引的时候) 所以后来倒出的cdmp和cdmp实际上包含的数据都已经是不对的测试已经没有意义了于是我重新进行试验在变换数据库字符集后删掉原来的数据库emp表中的数据插入正确的数据保证源数据库中的数据是可用的重新测试 然后把A机器上的数据库变换字符集就是原来是中文的数据库我换成英文原来是英文的数据库我换成中文采用的方法是修改props$表 三A机器上的数据库变换字符集后 C机器上导出操作C机器是英文字符集 exp system/manager@c file=c:cdmp owner=test exp system/manager@e file=c:edmp owner=test 都导出成功 发现上面两个文件的ACSII字符集都是 四A机器上的数据库变换字符集后 C机器上导出操作C机器是中文字符集 exp system/manager@c file=c:cdmp owner=test exp system/manager@e file=c:edmp owner=test 都导出成功 发现上面两个文件的ACSII字符集都是 备份上面导出的个数据文件 这时候修改上面导出的个文件的ACSII字符集进行中英文互换把和互换 修改后的文件名都加了一个_标记 小结 导出的时候如果客户端和数据库的字符集设置不一致导出的时候Oracle并没有提示 导出文件的ACSII字符集和客户端的字符集设置有关与被导数据库字符集的设置无关 **************************************** **** 导入操作 **** **************************************** 一向B的c倒入操作客户机D是英文字符集 D机器是英文字符集B机器是中文数据库 imp system/manager@c file=c:cdmp fromuser=test touser=test ignore=y C数据库字符集是中文cdmp是英文客户端导出的中文数据库文件ASCII字符集是英文的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是乱码(注意乱码不是问号)实际上导入失败 D机器是英文字符集B机器是中文数据库 imp system/manager@c file=c:c_dmp fromuser=test touser=test ignore=y C数据库字符集是中文c_dmp是英文客户端导出的中文数据库文件ASCII字符集是改成中文的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是乱码(注意乱码不是问号)实际上导入失败 D机器是英文字符集B机器是中文数据库 imp system/manager@c file=c:cdmp fromuser=test touser=test ignore=y C数据库字符集是中文cdmp是中文客户端导出的中文数据库文件ASCII字符集是中文的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是乱码(注意乱码不是问号)实际上导入失败 D机器是英文字符集B机器是中文数据库 imp system/manager@c file=c:c_dmp fromuser=test touser=test ignore=y C数据库字符集是中文c_dmp是中文客户端导出的中文数据库文件但是ASCII字符集是改成英文的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是乱码(注意乱码不是问号)实际上导入失败 D机器是英文字符集B机器是中文数据库 imp system/manager@c file=c:cdmp fromuser=test touser=test ignore=y C数据库字符集是中文cdmp是英文客户端导出的英文数据库文件但是数据库是换过的ASCII字符集是英文的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是乱码(注意乱码不是问号)实际上导入失败 D机器是英文字符集B机器是中文数据库 imp system/manager@c file=c:c_dmp fromuser=test touser=test ignore=y C数据库字符集是中文c_dmp是英文客户端导出的英文数据库文件但是数据库是换过的但是ASCII字符集是改成中文的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是???(注意问号不是乱码)实际上导入失败 D机器是英文字符集B机器是中文数据库 imp system/manager@c file=c:cdmp fromuser=test touser=test ignore=y C数据库字符集是中文cdmp是中文客户端导出的英文数据库文件但是数据库是换过的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是乱码(注意乱码不是问号)实际上导入失败 D机器是英文字符集B机器是中文数据库 imp system/manager@c file=c:c_dmp fromuser=test touser=test ignore=y C数据库字符集是中文c_dmp是中文客户端导出的中文数据库文件但是数据库是换过的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是乱码(注意乱码不是问号)实际上导入失败 D机器是英文字符集B机器是中文数据库 imp system/manager@c file=c:edmp fromuser=test touser=test ignore=y C数据库字符集是中文edmp是英文客户端导出的英文数据库文件 ASCII字符集是英文的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是乱码(注意乱码不是问号)实际上导入失败 D机器是英文字符集B机器是中文数据库 imp system/manager@c file=c:e_dmp fromuser=test touser=test ignore=y C数据库字符集是中文e_dmp是英文客户端导出的英文数据库文件但是ASCII字符集是换成中文的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是???(注意问号不是乱码)实际上导入失败 D机器是英文字符集B机器是中文数据库 imp system/manager@c file=c:edmp fromuser=test touser=test ignore=y C数据库字符集侵形模?edmp是中文客户端导出的英文数据库文件ASCII字符集是中文的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是乱码(注意乱码不是问号)实际上导入失败 D机器是英文字符集B机器是中文数据库 imp system/manager@c file=c:e_dmp fromuser=test touser=test ignore=y C数据库字符集是中文e_dmp是中文客户端导出的英文数据库文件但是ASCII字符集是换成英文的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是乱码(注意乱码不是问号)实际上导入失败 D机器是英文字符集B机器是中文数据库 imp system/manager@c file=c:edmp fromuser=test touser=test ignore=y C数据库字符集是中文edmp是英文客户端导出的中文数据库文件但是数据库是换过的ASCII字符集是英文的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是???(注意问号不是乱码)实际上导入失败 D机器是英文字符集B机器是中文数据库 imp system/manager@c file=c:e_dmp fromuser=test touser=test ignore=y C数据库字符集是中文e_dmp是英文客户端导出的中文数据库文件但是数据库是换过的但是ASCII字符集是换成中文的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是???(注意问号不是乱码)实际上导入失败 D机器是英文字符集B机器是中文数据库 imp system/manager@c file=c:edmp fromuser=test touser=test ignore=y C数据库字符集是中文edmp是中文客户端导出的中文数据库文件但是数据库是换过的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是???(注意问号不是乱码)实际上导入失败 D机器是英文字符集B机器是中文数据库 imp system/manager@c file=c:e_dmp fromuser=test touser=test ignore=y C数据库字符集是中文e_dmp是中文客户端导出的中文数据库文件但是数据库是换过的但是ASCII字符集是换成英文的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是乱码(注意乱码不是问号)实际上导入失败 小结 导入的时候如果客户端和数据库的字符集设置不一致导入的时候Oracle并没有提示 导入的时候如果客户端和数据库的字符集设置不一致ORACLE不进行字符集验证最终结果是数据库不可用 至于是乱码还是问号我没有总结因为没有必要反正是数据库不可用 上面的操作其实没有必要做因为导入的客户端和目的数据库字符集不一致导入后肯定不能用但是为了试验的完整性我还是自己做了一遍希望大家不要嫌烦 二向B的c倒入操作客户机是中文字符集 D机器是中文字符集B机器是中文数据库 imp system/manager@c file=c:cdmp fromuser=test touser=test ignore=y C数据库字符集是中文cdmp是英文客户端导出的中文数据库文件ASCII字符集是英文的 提示不支持要求的字符集转换倒入失败 D机器是中文字符集B机器是中文数据库 imp system/manager@c file=c:c_dmp fromuser=test touser=test ignore=y C数据库字符集是中文c_dmp是英文客户端导出的中文数据库文件ASCII字符集是改成中文的 导入成功有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是乱码(注意乱码不是问号)实际上导入失败 D机器是中文字符集B机器是中文数据库 imp system/manager@c file=c:cdmp fromuser=test touser=test ignore=y C数据库字符集是中文cdmp是中文客户端导出的中文数据库文件ASCII字符集是中文的 导入成功有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是???(注意问号不是乱码)实际上导入失败 D机器是中文字符集B机器是中文数据库 imp system/manager@c file=c:c_dmp fromuser=test touser=test ignore=y C数据库字符集是中文c_dmp是中文客户端导出的中文数据库文件但是ASCII字符集是改成英文的 提示不支持要求的字符集转换倒入失败 D机器是中文字符集B机器是中文数据库 imp system/manager@c file=c:cdmp fromuser=test touser=test ignore=y C数据库字符集是中文cdmp是英文客户端导出的英文数据库文件但是数据库是换过的ASCII字符集是英文的 提示不支持要求的字符集转换倒入失败 D机器是中文字符集B机器是中文数据库 imp system/manager@c file=c:c_dmp fromuser=test touser=test ignore=y C数据库字符集是中文c_dmp是英文客户端导出的英文数据库文件但是数据库是换过的但是ASCII字符集是改成中文的 导入成功有报错信息 用英文字符集客户端是???问号用中文客户端是正确结果可以看到中文 实际上导入成功 D机器是中文字符集B机器是中文数据库 imp system/manager@c file=c:cdmp fromuser=test touser=test ignore=y C数据库字符集是中文cdmp是中文客户端导出的英文数据库文件但是数据库是换过的ASCII字符集是中文的 导入成功有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是乱码(注意乱码不是问号)实际上导入失败 D机器是中文字符集B机器是中文数据库 imp system/manager@c file=c:c_dmp fromuser=test touser=test ignore=y C数据库字符集是中文c_dmp是中文客户端导出的中文数据库文件但是数据库是换过的ASCII字符集是换成英文的 提示不支持要求的字符集转换倒入失败 D机器是中文字符集B机器是中文数据库 imp system/manager@c file=c:edmp fromuser=test touser=test ignore=y C数据库字符集是中文edmp是英文客户端导出的英文数据库文件ASCII字符集是英文的 提示不支持要求的字符集转换倒入失败 D机器是中文字符集B机器是中文数据库 imp system/manager@c file=c:e_dmp fromuser=test touser=test ignore=y C数据库字符集是中文e_dmp是英文客户端导出的英文数据库文件但是ASCII字符集是换成中文的 导入成功有报错信息 用英文字符集客户端是???问号用中文客户端是正确结果可以看到中文 实际上导入成功 D机器是中文字符集B机器是中文数据库 imp system/manager@c file=c:edmp fromuser=test touser=test ignore=y C数据库字符集是中文edmp是中文客户端导出的英文数据库文件ASCII字符集是中文的 导入成功有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是乱码(注意乱码不是问号)实际上导入失败 D机器是中文字符集B机器是中文数据库 imp system/manager@c file=c:e_dmp fromuser=test touser=test ignore=y C数据库字符集是中文e_dmp是中文客户端导出的英文数据库文件但是ASCII字符集是换成英文的 提示不支持要求的字符集转换倒入失败 D机器是中文字符集B机器是中文数据库 imp system/manager@c file=c:edmp fromuser=test touser=test ignore=y C数据库字符集是中文edmp是英文客户端导出的中文数据库文件但是数据库是换过的ASCII字符集是英文的 提示不支持要求的字符集转换倒入失败 D机器是中文字符集B机器是中文数据库 imp system/manager@c file=c:e_dmp fromuser=test touser=test ignore=y C数据库字符集是中文e_dmp是英文客户端导出的中文数据库文件但是数据库是换过的但是ASCII字符集是换成中文的 导入成功有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问C数据库是???(注意问号不是乱码)实际上导入失败 D机器是中文字符集B机器是中文数据库 imp system/manager@c file=c:edmp fromuser=test touser=test ignore=y C数据库字符集是中文edmp是中文客户端导出的中文数据库文件但是数据库是换过的 导入成功有报错信息 用英文字符集客户端是???问号用中文客户端是正确结果可以看到中文 实际上导入成功 D机器是中文字符集B机器是中文数据库 imp system/manager@c file=c:e_dmp fromuser=test touser=test ignore=y C数据库字符集是中文e_dmp是中文客户端导出的中文数据库文件但是数据库是换过的但是ASCII字符集是换成英文的 提示不支持要求的字符集转换倒入失败 小结 :导入的时候只有当客户机和服务器的字符集一致的时候才进行倒入的字符集验证当导入文件(DMP文件)的ASCII字符集和他们一致的时候才能导入否则报:不支持要求的字符集转换 :必要条件是导出文件是可用的就是说导出的时候的客户端和服务器端的字符集是一致的可以解释和的成功 :的成功说明了就算是英文的数据库保存中文数据在导出后修改DMP文件的字符集还是可以导入到中文数据库中的 :的成功说明了就算数据库是转换过的但是还是可以正确导出中文数据的 :的成功说明了就算是英文的数据库保存中文数据在导出后修改DMP文件的字符集还是可以导入到中文数据库中的(即使这个英文数据库原来是中文的) :最不可理解的是为什么不行按道理说它应该是最有把握的 三向B的e倒入操作(数据库是英文数据库)客户机D是英文字符集 备注客户机是中文字符集的情况其实不用测试了因为客户机和服务器不一致肯定出现问题 D机器是英文字符集B机器是英文数据库 imp system/manager@e file=c:cdmp fromuser=test touser=test ignore=y cdmp是英文客户端导出的中文数据库文件ASCII字符集是英文的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问E数据库是乱码(注意乱码不是问号)实际上导入失败 D机器是英文字符集B机器是英文数据库 imp system/manager@e file=c:c_dmp fromuser=test touser=test ignore=y c_dmp是英文客户端导出的中文数据库文件ASCII字符集是改成中文的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问E数据库是乱码(注意乱码不是问号)实际上导入失败 D机器是英文字符集B机器是英文数据库 imp system/manager@e file=c:cdmp fromuser=test touser=test ignore=y cdmp是中文客户端导出的中文数据库文件ASCII字符集是中文的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问E数据库是乱码(注意乱码不是问号)实际上导入失败 D机器是英文字符集B机器是英文数据库 imp system/manager@e file=c:c_dmp fromuser=test touser=test ignore=y c_dmp是中文客户端导出的中文数据库文件但是ASCII字符集是改成英文的 导入成功没有报错信息 但是不管用中文客户端还是用英文客户端SQL/PLUS访问E数据库是乱码(注意乱码不是问号)实际上导入失败 D机器是英文字符集B机器是英文数据库 imp system/manager@e file=c:cdmp fromuser=test touser=test ignore=y cdmp是英文客户端导出的英文数据库文件但是数据库是换过的ASCII字符集是英文的 导入成功没有报错信息 用英文客户端SQL/PLUS访问E数据库是中文实际上导入成功 D机器是英文字符集B机器是英文数据库 imp system/manager@e file=c:c_dmp fromuser=test touser=test ignore=y >c_dmp是英文客户端导出的英文数据库文件但是数据库是换过的但是ASCII字符集是改成中文的 导入成功没有报错信息 用英文客户端SQL/PLUS访问E数据库是???倒入不成功 |