浅谈基于Oracle9i的国际化移植

最近做了一次Oracle国际化移植实践。为了安全准确地达到这一目的,查阅了一些有用的资料,现简要地将思路和过程介绍一下。

 
第一篇、概念
 
作为Oracle的国际化移植来说,首先要了解Oracle的内置数据类型和编码方式。暂且可以简单地认为Oracle内置的和文字文本有关的数据类型有两套。
 
第一套:
CHAR
VARCHAR/VARCHAR2
LOB
 
第二套:
NCHAR
NVARCHAR/NVARCHAR2
NLOB
 
字面上看这两套数据类型的差别仅仅在于后者多了首字母“N”,这个“N”的含义是“国际化”,在底层的含义是针对这样的数据类型“使用Unicode编码”。也就是说Oracle的文字文本数据类型有两套,第一套用于支持本地化编码格式(例如GB2312/SHIFT-JIS等),第二套用于支持Unicode编码,Oracle支持的Unicode编码方式有两种,分别是UTF8和UTF16,缺省使用UTF16。
 
这又关系到Oracle底层的文本编码方式,我们在Oracle的安装过程中创建数据库实例之前选择的文本编码方式,需要注意这是针对第一套数据类型的“本地字符编码”,在开始配置数据库创建脚本的过程中我们需要指定另一个文本编码方式,只有“UTF8”和“UTF16”可选,缺省选择UTF16,这里的编码方式就是针对第二套数据类型的“国际化编码”或者说“Unicode编码”。(要注意如果创建数据库的时候选择的配置方案是“通用型数据库”,那么这一步不用手工选择,只是被缺省地指定为UTF16。)
 
第二篇、提案
 
有了上面的基本认识之后我们便可以探讨Oracle数据库Unicode移植的具体方案。以下逐一简要探讨。
 
从影响面的角度考虑,可以分为“局部Unicode化”和“全盘Unicode化”。所谓局部Unicode化,从操作上来说就是有选择地只将部分文本型字段的数据类型从第一套相应地转换为第二套,例如把CHAR转换为NCHAR,把VARCHAR2转换为NVARCHAR2;所谓全盘Unicode化,则是将本地字符编码修改为UTF8,这样一来第一套数据类型在底层也会被按照UTF8编码进行存储。
 
Oracle数据库的Unicode移植并不能保证100%安全准确(任何一种数据库都不能),成功与否,取决于移植方案是否考虑充分到位,其中主要问题是字符集以及字符编码方案之间的兼容性。这就要求我们在正式移植之前需要做一些必要的试验,并且要详细考虑以下问题:
 
※字符集与字符集之间的集合关系
 举个例子说,ASCII字符集是其它任何一个字符集的子集,把ASCII编码的数据库移植到其它任何一种字符集编码都不会出现字符集的兼容问题。简单地说,从子集到超集的移植是完全安全的,但是从超集到子集(例如从UTF16到SHIFT-JIS)或者从某集合到同级集合(例如从GB2312到SHIFT-JIS)的移植是不安全的需要全面分析的。
 
※编码转换过程中的字段长度限制问题
 显然,对于同一个字符,使用不同的字符集编码方式进行编码,得到的字节序列是不一样的,例如一个字母“A”,使用ASCII进行编码的话,是0x41,如果使用UTF-16进行编码,则是0x0041,前者占用1个字节,后者占用2个字节;汉字也是类似的情况,同样一个汉字,如果使用GB2312进行编码,那么肯定占用2个字节,如果使用UTF-8进行编码,将占用3个字节,而如果使用UTF-16进行编码,将可能占用2~3个字节。那么如果使用“全盘Unicode化”的方案,CHAR和VARCHAR2等数据类型也会按照UTF-8进行编码,假设移植前的本地编码是GB2312,字段声明是CHAR(10),可以存储5个汉字,移植到UTF-8之后,将最多只能存储3个汉字,那么以前存储的记录中,如果有超过3个汉字的数据,将导致转换失败或者数据导入失败。
 
 同时,还需要考虑“字节数”和“字符数”的不同,缺省地,声明VARCHAR2类型的字段时,指定的长度约束是“字节数”(例如VARCHAR2(10)),除非使用“VARCHAR2(10 char)”这种方式声明,才是字符数;对于NVARCHAR2来说,长度约束缺省地就是字符数,NVARCHAR2(10)的含意是约束最大10个字符,而不是10个字节。另外,数据类型声明中所支持的最大字符或字节数也因编码方式的不同而不同,更详细的规则请参考文章后面的文档。
 
※编码转换过程中的字符丢失问题
 参考上述的集合关系问题,因为我们本次的移植是非Unicode到Unicode,所以不会导致字符丢失,但是如果是不安全的集合关系的话就需要做周全的评估了。
 
※本地字符集和国际化字符集的显式转换以及隐式转换
 这个问题考虑的是第一套数据类型和第二套数据类型之前的转换关系。简单地说,从第一套到第二套的隐式转换是安全的(LOB和NLOB例外),而从第二套到第一套的转换是不安全的。在SQL语句里面,我们可以使用隐式转换方式也可以使用显式转换方式。详细的描述请参考《Oracle9i Database Globalization Support Guide》。
 
※针对应用程序的国际化移植
 受Unicode化移植影响的应用程序大致有以下几种:PL/SQL、OCI、JDBC。Oracle为每一种应用程序都提供了相应的解决方案,因为我们本次移植相关的应用程序不是上述三种类型,所以不需要考虑。如果需要考虑这些问题,请参考《Migration to Unicode Datatypes for Multilingual Databases and Applications》中的相关章节,《Oracle9i Database Globalization Support Guide》中也有详细的阐述。
 
第三篇、实践
 
总体来说,我们本次采用的是“局部Unicode化”方案,对于可能包含ASCII以外字符的字段,将其数据类型从第一套转换为第二套(安全转换),对于只包含ASCII字符的字段,保持原有的SHIFT-JIS编码不变(因为SHIFT-JIS是ASCII的超集),数据长度的约束照原。
 
过程方面
1、创建一个新的数据库实例,本地编码指定为SHIFT-JIS,国际化编码指定为UTF16。
2、从原始数据库的Schema导出所有表(包含数据)
3、在新数据库实例创建一个用户,导入阶段2导出的表和数据
4、使用ALTER TABLE MODIFY语句的脚本将指定字段的数据类型从第一套转换到第二套
   (注意LOB除外,LOB要作特殊处理,具体请参考后面的文档)
5、测试、验证
6、用新的数据库实例替代原有的数据库实例
 
参考文献(可从www.oracle.com获取):
《Oracle9i Database Globalization Support Guide》
《Character Set Migration Best Practices》
《Migration to Unicode Datatypes for Multilingual Databases and Applications》
------------------------
※2008年3月30日注:
  这篇文章是有一些谬误的。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值