日期:2014-05-16  浏览次数:20426 次

Oracle数据库多语言文字存储解决方案[转]
一、关于字符集

字符集(也称字元集,Character Set)就是字符编码表(codepage),一个字符不论英文、中文、韩文等在计算机系统内存或硬盘中通过二进制的字节(Byte)保存,这个二进制的编码就是字符编码(也称内码),字符集就是字符与内码的对应(映射)表。
    因为多国语言的原因,就出现了根据本国语言制作的字符集。如使用最广泛的ASCII编码,由美国国家标准局(即ANSI)制定,适用于所有拉丁、英文字符。中国大陆使用GB2312,GBK,GB18030等字符集,这些字符集包含所有汉字字符的内码,其中GBK,GB18030称为大字符集,对繁体中文也进行了编码。香港、台湾、澳门地区使用Big5编码,Big5收录了繁体中文(有些繁体与中国大陆繁体字符有差异)的编码,不包含简体中文的字符编码。韩文使用euc-kr的字符集,韩文中也有很多汉字,所以字符集包括很多汉字字符的编码。其他如日文、俄文等都有自己国家制定的字符集,用来保证计算机系统能正确显示本国的语言文字。不同语言的字符集不具有通用性,ASCII字符集没有制定中文字符的编码,GB2312没有制定韩文字符的编码,Big5没有制定简体中文字符的编码,针对这种不兼容性,官方发布了Unicode(进一步优化的UTF7,UTF8,UTF16等)字符集,对每一种语言的每个字符制定了统一且唯一的内码,满足跨语言、跨平台的字符解码和转换处理。

字符集编码(16进制)示例:

字符/字符集
GBK
Euc-kr 
UTF8
UTF16 
物流
ce-ef ,c1-f7
da-aa,d7-b5
e7-89-a9,e6-b5-81
72-69,6d-41
??

bb-ef ,bc-ba
ec-82-bc,ec-84-b1
c0-bc,c1-31

注:
1)       字符“??”在韩文字符集Euc-kr中的编码是bb-ef-bc-ba,在GBK字符集中是没有“??”这两个字符的,也就是说bb-ef-bc-ba在Euc-kr与GBK编码对照表中是没有记录的,如果你硬是要GBK字符集来对“??”作出解释(解码),那GBK就用字符“?”(因韩文字符是两个字节,所以使用全角?)代替,全角?的编码在GBK中是a3-bf。
2)       汉字“物流”字符在Euc-kr中的编码是da-aa,d7-b5,这说明韩文字符集中包含了部分汉字的编码,当然这个编码与GBK字符集中“物流”两个字符的编码(ce-ef ,c1-f7)是不同的,用GBK去解释韩文字符集中“物流”两个字符,显示的结果肯定不是“物流”两个字符。同样的,在GBK中很多繁体中文字符的编码与BIG5中相同繁体中文的字符编码也是不同的,例如你在简体中文环境开发应用程序时,窗体控件使用繁体中文表示,但是在繁体OS运行应用程序,控件上的繁体中文变成了乱码或?,原因就是不同字符集同样字符的编码是不同的,解决这个问题的方法就是将应用程序使用unicode编码保存,告诉操作系统使用unicode字符集对你的应用程序中的字符进行解码。

    Windows操作系统(OS)的字符集:不同语言的OS的默认字符集是不一样的。英文OS使用ASCII字符集作为系统的字符集,简体使用GB2312,繁体使用Big5(在VB.NET中,可用System.Text.Encoding.Default.EncodingName检查OS的字符集)。Windows系统本身对系统默认的字符集有很好的支持,但是安装在OS上的应用程序却不一定这样。例如,在一个简体中文操作系统上安装了韩文版的某个应用程序,这个应用程序在开发时使用的是euc-kr字符集编码。因为OS默认的处理非Unicode程序的字符集是GB2312,在 GB2312字符集并未对任何韩文字符进行编码,在GB2312内找不到任何一个韩文字符的内码,找不到只能以“?”代替这个字符,对应的编码变成了“?”的编码,例如:“??”这两个韩文字符在程序运行时显示的是“?”。解决这个问题,有三种方法:1,该韩文应用程序使用Unicode编码保存。在简体环境运行时,OS使用Unicode字符集解码,只要系统安装韩文字体,就可正常显示韩文;2,将OS处理非Unicode程序使用的字符集改为euc-kr,支持韩文应用程序的解码(在control panel->Regional and Language Options 修改);3,安装微软的AppLocale工具,指定该韩文应用程序运行时使用euc-kr的字符集。
一、Oracle字符集
Oracle字符集包括两部分。一部分是Server端数据库运行实例(instance)的字符集,一部分是Oracle客户端Client的字符集。
1,  数据库实例的字符集(以Oracle 10g为例)

 
在安装Oracle数据库过程中,可以选择数据库字符集。默认的是OS系统的字符集,如简体中文系统是GB2312,繁体系统是BIG5。Oracle对于简体系统的字符集使用ZHS16GBK,GBK是GB2312的超集,Oracle不识别GB2312,只认ZHS16GBK。此外,选择Unicode作为数据库字符集,所有存储数据都将以Unicode编码存储在数据库中,不论字段类型是Number,varchar2,DateTime等。或者也可以从字符集列表中选择其他字符集。注意到有个国家字符集的选项,而且国家字符集的选择只有unicode,这是为当数据库字符集为非Unicode时将数据存为Unicode编码时用到。比如:数据库字符集为ZHS16GBK,数据库表mer_categ的一个字段为S_merc_name,数据类型为varchar2,存入中文字符“物流”,“物流”这两个字符使用GBK字符集编码存储。通过“select dump(s_merc_name,16) from mer_categ”查询该字段在数据库中的内码得到结果是:ce,ef ,c1,f7,这与我们在前面看到的示例表中这两个字的内码是一致的。现在,把S_merc_name这个字段类型改为nvarchar2,意味着这个字段数据的存储将使用National Charset(国家字符集)——AL16UTF16的编码存储。同样写入“物流”两个中文字符,再次查询该数据在数据库中的内码结果是:e7,89,a9e6,b5,81,这就是我们为什么使用nvarchar2作为字段类型的原因。回过头来看,如果数据库字符集选择了Unicode,那表字段中使用nvarchar2已经没什么意义了,因为所有字段类型的数据都是使用Unicdoe编码来保存的。
查询数据库字符集的sql指令是:
“select * from v$nls_parameters”
得出结果:

NLS_LANGUAGE
SIMPLIFIED CHINESE
NLS_TERRITORY
CHINA
NLS_CURRENCY

NLS_ISO_CURRENCY
CHINA
NLS_NUMERIC_CHARACTERS
.,
NLS_CALENDAR
GREGORIAN
NLS_DATE_FORMAT
DD-MON-RR
NLS_DATE_LANGUAGE
SIMPLIFIED CHINESE
NLS_CHARACTERSET
AL32UTF8
NLS_SORT
BINARY
NLS_TIME_FORMAT
HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT
DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT
HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT
DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY

NLS_NCHAR_CHARACTERSET
UTF8
NLS_COMP
BINARY
NLS_LENGTH_SEMANTICS
BYTE
NLS_NCHAR_CONV_EXCP
FALSE


其中NLS_CHARACTERSET 是数据库的字符集;NLS_NCHAR_CHARACTERSET是国家字符集。
数据库的字符集在建立数据库的时候创建。目前也有方法转换字符集,但两个字符集