作为一个Oracle数据库的用户对于Export和Import两个命令绝对不会感到陌生因为这二者正是我们经常用于数据备份和恢复的工具但在使用这两个命令过程中所发生的Oracle字符集问题常给一些Oracle使用者带来不必要的麻烦和不必要的数据损失本文将就Export和Import过程中Oracle字符集的转换规律及使用这两个命令的注意事项做一总结
字符集转换的原因
ExportImport过程如上图所示从这个示意图中可以看到有四处关系到字符集而这四处字符集的不一致恰恰是导致Oracle进行字符集转换的原因
* 源数据库字符集
* Export过程中用户会话字符集
* Import过程中用户会话字符集
* 目标数据库字符集
在Export和Import过程中如果存在影响字符集转换的四因素不一致则可能发生Oracle字符集转换即
在Export过程中如果源数据库字符集与Export用户会话字符集不一致会发生字符集转换并在导出的二进制格式Dmp文件的头部几个字节中存储Export用户会话字符集的ID号在这个转换过程中可能发生数据的丢失
例: 如果源数据库使用ZHSGBK而Export用户会话字符集使用USASCII由于ZHSGBK是位字符集而USASCII是位字符集这个转换过程中中文字符在USASCII中不能够找到对等的字符所以所有中文字符都会丢失而变成?? 形式即这种转换后生成的Dmp文件已经发生了数据丢失
例: 如果源数据库使用ZHSGBK而Export用户会话字符集使用ZHSCGB但由于ZHSGBK字符集是ZHSCGB字符集的超集这个过程中绝大部分字符都能够正确转换只有一些超出ZHSCGB字符集的字符变为?? 形式如果源数据库使用ZHSCGB字符集而Export用户会话使用ZHSGBK字符集则转换过程能够完全转换成功
在Import向目标数据库转换过程中其字符集发生转换的情况正好与Export过程相反这里不再详述
在Export导出的Dmp文件中含有Export用户会话字符集在Import过程中首先发生的是Dmp文件字符集(即Export用户会话字符集)向Import用户会话字符集的转换如果这个转换过程不能正确完成Import向目标数据库的导入过程也就不能完成
进行字符集的正确转换
通常情况下我们在使用Oracle的Export和Import过程中并不希望发生字符的转换但有时这种转换却是必要的如我们在安装Oracle数据库时选择ZHSCGB字符集由于这种字符集是一种中文小字符集对于一些汉字不能够正确表示这需要通过使用ZHSGBK字符集得到解决此时就要进行字符集的转换
为了确保ExportImport过程中Oracle字符集不发生转换或正确转换建议最好在进行这个过程前检查一下源数据库字符集与Export用户会话字符集是否一致源数据库字符集与目标数据库字符集是否一致目标数据库字符与Import用户会话字符集是否一致如果能够保证这四个字符集是一致的则在ExportImport过程中Oracle字符集就不用发生转换
可用以下办法检查数据库字符集:
通过InitXXXXora文件进行查看
借助SQL语句查看 SELECT NAMEVALUE$ FROM SYSPROPS$ WHERE NAME=NLS_CHARACTERSET
对于ExportImport用户会话字符集在Windows系统中也可以通过注册表中的NLS_LANG进行查看或修改对于Unix系统则可通过设置用户的环境变量NLS_LANG来查看或修改
特别要注意的是Oracle数据库字符集通常是在创建时确定一旦存储用户数据后就不要再修改了因为其数据都是使用该字符集进行存储的改换其他字符集之后原有数据就不能够正确表示了但如果确实想进行字符集改变则可通过以下几步来实现
备份数据库后删除原数据(可物理备份如使用Export请注意确保字符集不发生转换或数据无损失)
使用Internal用户更新sysprops$表中的字符集:
Update sysprops$ set name=DestCharSet Where name=NLS_CHARACTERSET; COMMIT;
重启数据库
恢复数据
下面字符集之间的转换是可行的
字符集子集向字符集父集转换是可行的如ZHSCGB向ZHSGBK转换而字符集父类向字符集子集进行转换时会损失部分数据
只包含英文字符数据的双字节字符集也可向单字节字符集转换如ZHSGBK(English Only)可以向USASCII正确转换
编码范围相同的单字节字符集之间通常可以进行相互转换
请注意这里所说的没有数据损失是指一种字符集A转换成另一种字符集B之后可以再从字符集B正确转换成字符集A或字符集B能够正确表示字符集A中转换过来的数据
字符集对程序的影响
根据一个字符需要多少位字节来表示可以把字符集分为单字节字符集和多字节字符集其中单字节字符集又分为位字符集和位字符集单字节位编码字符集有USASCⅡ单字节位编码字符集有符合ISO 标准规定的WEISOP等多字节编码又分为固定长度(长度大于或等于)编码模式和不固定长度编码模式多字节编码字符集中的ZHSGBKZHSCGBJASJIS等是采用两个字节表示一个字符的字符集又叫双字节字符集
一个英文字母是一个字符一个中文汉字是几个字符呢?我们知道一个中文汉字是双字节字符但它有几个字符与其数据库字符集有关如果数据库字符集使用单字节USASCII则一个中文汉字是二个字符如果数据库字符集使用双字节字符集ZHSGBK则一个中文汉字是一个字符有关这一点可以使用Oracle的函数Substr得到证明
使用USASCⅡ字符集时:
Select substr(东北大学) from dual;
语句执行结果返回东
使用ZHSGBK字符集时:
Select substr(东北大学) from dual;
语句执行结果返回东北
选择合适的数据库字符集
选择数据库字符集时应考虑以下事项
.数据库需要支持什么语言
在为数据库选择字符集时常会发现几种字符集都适合你当前语言需求如简体中文就有ZHSGBK和ZHSCGB等字符集可供选择应选择哪种?在选择字符集时应考虑到数据库将来的系统需求如果知道将来数据库要扩展支持不同的语言选择一个范围较广的字符集会是一个更好的主意
.系统资源与应用之间的互作用性
选择的数据库字符集应保证操作系统与应用之间的无缝连接如果选择的字符集不是操作系统有效的字符集则系统就需要在这两者之间做字符转换在这种字符转换过程中就有可能发生一些字符丢失现象从一种字符集A向另一种字符集B转换过程中A中的字符必须在B中可以找到等价的字符否则就会以?来代替从这个意义上说如果两种字符集编码范围是相同的则可以相互转换
字符集转换过程中会影响系统性能因此应保证客户端和服务器端有相同的字符集以避免字符集转换也可以提高一定的系统性能
.系统的性能要求
不同的数据库字符集对于数据库的性能是有一定影响的为了得到最好的数据库性能选择的数据库字符集应避免字符转换并且要选择对于期望的语言有最高效的编码效率通常单字节字符集比多字节字符集有更优的性能表现在空间需求方面也更小些
.其他一些限制
在为数据库选择一个合适的字符集时应参考Oracle对应版本的相关文档检查Oracle对于一些字符集的限制如Oracle 版本中以下字符集是不能使用的: JAEUCFIXEDZHSGBKFIXEDJADBCSFIXEDKODBCSFIXEDZHSDBCSFIXEDJASJISFIXEDZHTTRISFIXED
综上所述正确理解Oracle字符集的转换过程可以使我们避免不必要的麻烦和数据损失合理利用Oracle字符集的转换过程也可以帮助我们正确地从一种字符集转换到另一种字符集以满足我们各种不同的应用需求