- 浏览: 40234 次
- 性别:
- 来自: 北京
文章分类
最新评论
一、关于字符集
字符集(也称字元集,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是国家字符集。
数据库的字符集在建立数据库的时候创建。目前也有方法转换字符集,但两个字符集的转换还是存在风险,造成数据丢失或错误,不建议使用。
2, Oracle Client字符集(NLS_LANG)
在访问Oracle的客户端安装Oracle Client过程中并没有选项选择Oracle Client的字符集,安装完毕后在注册表HKLOCAL_MACHINE\SOFTWARE\ORACLE\KEY_ORACLECLENT_HOME1\可以找到NLS_LANG键,值为当前OS的字符集。如简体系统为:ZHS16GBK,繁体系统为:MSWIN950。可见,Oracle Client(以下简称NLS_LANG)在安装过程中选择了OS的字符集作为默认的NLS_LANG字符集。
设定NLS_LANG有三种方法:
a) 修改注册表。将HKLOCAL_MACHINE\SOFTWARE\ORACLE\KEY_ORACLECLENT_HOME1\下NLS_LANG键值改为你要设定的字符集,如将SIMPLIFIED CHINESE_CHINA.ZHS16GBK改为:SIMPLIFIED CHINESE_CHINA.AL32UTF8。但这种做法似乎无效,即使重新启动机器后,也没有生效,NLS_LANG仍使用当初安装时的OS字符集。
b) 设定环境变量。在My Computer->Properties->Advanced->Environment Variables->System Variables 新增环境变量设置,如:Variable name=NLS_LANG,Variable Value= SIMPLIFIED CHINESE_CHINA.AL32UTF8。这样NLS_LANG字符集为UTF8,这个NLS_LANG优先序高于注册表中的NLS。注意:环境变量设在系统变量中(System Vairables),而不是用户变量(User Vairables)。
c) 在应用程序运行的Process Session中设定。在程序运行之前,先通过set NLS_LANG=进程Session的字符集。例如:
Echo %nls_lang%,在这个session中,已经设定NLS_LANG字符集为ZHS16GBK。同样,你也可以新开一个CMD窗口,设定另一种NLS_LANG字符集。这种在session中设定NLS_LANG的优先序高于系统环境变量NLS_LANG。注册表NLS_LANG、系统环境变量NLS_LANG、Session NLS_LANG的优先序是:Session NLS_LANG > 系统环境变量NLS_LANG > 注册表NLS_LANG。
三、Oracle数据库如何存储多国文字
首先,先看一个有趣的问题。我们要保存的文字哪里来?一种方法是在屏幕上输入,输入中文时,我们打开自己习惯的输入法,在应用程序给你提供的输入框内输入文字;还有一种方法是复制粘贴的方法,将文字从网页、文档中拷贝后再粘贴到输入框中,那问题是:输入框中的文字使用的字符集是什么?有人说,是客户端操作系统的默认字符集。好,我的操作系统是简体中文,默认系统字符集是GB2312,在输入框中输入韩文字符“삼성”,如果这两个韩文字符是用GB2312字符集解码的,输入框内应该显示两个“?”,因为GB2312字符集内没有韩文字符只能用“?”代替。但是现在这两个韩文字符在输入框内正常的显示,说明这两个韩文的字符集是支持韩文字符的字符集,是韩文字符集“euc-kr”,还是Unicode字符集?肉眼看不出来,也许查看一下内存中输入框中文字的编码能找到答案,喜欢钻研的人可以去看一看。表面来判断,可能是根据输入法使用的字符集,输入法使用什么样的字符集,输入的文字就是用的什么样的字符集。从网页上复制粘贴过来的文字,应该跟网页的字符集是一致的。其实,我们不关心多国文字背后的字符集是用的本国字符集还是unicode字符集,我们关心的是多国文字如何在数据库中被正确地存取。
以oracle 10g R2 10.2.0.3 作为测试数据库版本,在数据库建立一张表:
表名称:mer_categ,商品类别表
字段
数据类型
长度
说明
S_merc_id
Varchar2
20
分类编号
S_merc_name
Varchar2
50
分类名称
现在要新增一个分类编号为01,分类名称为“삼성”的记录。即使SQL的初学者也会写出:
Insert into mer_catag values (‘01’,’삼성’);
这条SQL语句没有错,但是能不能把“삼성”正确的写入数据库,仅仅靠一条SQL语句是不够的,在分析各种测试环境之前,我们看一段官方关于SQL语句中字符串字符编码的描述:
“Being part of a SQL or PL/SQL statement, the text of any literal, with or without the prefix N, is encoded in the same character set as the rest of the statement. On the client side, the statement is in the client character set, which is determined by the client character set defined in NLS_LANG, or specified in theOCIEnvNlsCreate() call, or predefined as UTF -16 in JDBC. On the server side the statement is in the database character set.”
这段话告诉我们:SQL语句提交到Server之前,SQL语句中的字符串部分(不管前面有没有N’)作为语句的一部分将被用NLS_LANG定义的字符集进行编码。提交到Server端后,再被数据库字符集编码。可以推出:如果数据库字符集与客户端NLS_LANG字符集一致,在Server端就没有必要再一次编码了。
在安装oracle数据库时如果一直选择“下一步”,数据库字符集将默认使用操作系统字符集。如在简体OS下,安装Oracle Server,创建Oracle实例后,实例的数据库字符集默认是ZHS16GBK;安装客户端后,NLS_LANG默认是ZHS16GBK字符集。GBK是汉字大字符集,处理汉字简繁体都可以,所以平时使用类似:
Insert into mer_catag values (‘01’,’中国’);
Insert into mer_catag values (‘01’,’中國’);
都是正常的。但是当处理多国文字时,就不灵了。如:
Insert into mer_catag values (‘01’,’삼성’);
根据前面引用的官方描述,这条SQL语句无论是字符串部分还是其他部分,将先被NLS_LANG定义的字符集转换,“삼성”将用GBK字符集转换,前面讲过,“삼성”转换后的字符是“??”(两个全角问号)。SQL语句变成了:
Insert into mer_catag values (‘01’,’??’);
在server端,因数据库字符集与NLS_LANG一致,SQL语句不再进行字符集转换,执行SQL后,数据库存储了两个全角“?”。用select dump(s_merc_name,16) from mer_categ验证一下,得到结果是:Typ=1 Len=4: a3,bf,a3,bf。“a3,bf”就是全角”?”的GBK编码。两个韩文字符被当作”?”存在了数据库中,查询出的当然也是”?”。所以,不对oracle字符集进行配置,不能正确处理多国文字的存储。
客户端的NLS能实现对多国文字进行正确字符集转换的话,毫无疑问是选择Unicode字符集。用set NLS_LANG =SIMPLE CHINESE.AL32UTF8可以修改客户端的NLS为UTF8字符集,还是以
Insert into mer_catag values (‘01’,’삼성’);
为例,在客户端,这条SQL语句使用UTF8字符集做了编码转换,韩文字符“삼성”的编码转为:“ec-82-bc,ec-84-b1”(UTF8编码)。下一步,关键看Server端的数据库字符集了,如果数据库字符集仍为GBK,也就是说,“삼성 ”要作UTF8->GBK的转码,能转成功吗?显然不可以,连个韩文字符又被全角“?”代替了。在server端,SQL语句被转成了:
Insert into mer_catag values (‘01’,’??’);
数据库又存了两个全角“?”。怎么办?Server端能不能不作字符集转换?前面提到,如果数据库字符集与客户端NLS_LANG字符集一致,在Server端就没有必要再一次编码了。好,那就在Server端将数据库字符集设为UTF8,韩文字符“삼성”就以UTF8的字符编码存到数据库里了。验证一下,select dump(s_merc_name,16) from mer_categ,结果是:Typ=1 Len=6: ec,82,bc,ec,84,b1。这个结果与前面看到的UTF8编码是一致的。所以,当数据库字符集与NLS_LANG(客户端)都设为UTF8字符集时,可以解决多国文字正确存储的问题。
似乎将数据库字符集与NLS_LANG都设为UTF8的做法未得到广泛应用,原因是大多数的应用不存在使用多国语言的问题?没做过相关调查。除此之外,使用UTF8存储数据占用更多的空间是事实存在的,一个汉字字符UTF8使用三个字节存储,而在GBK中使用两个字节,用GBK作为数据库字符集存储汉字更经济实惠些。最后,任何存入数据库的数据都先经过UTF8的转码再存储,必然带来效能的损失。那能不能区别对待存储的数据呢?例如只针对存在多国字符的数据使用Unicode字符集存储呢?这就是国家字符集(National Chartset)存在的原因。国家字符集是那些存放在NCHAR,NVARCHAR2,NCLOB字段中的数据的Unicode字符编码集,Oracle 10g使用AL16UTF16字符集作为默认的数据库国家字符集。如何将多国文字存储到NVARCHAR2这样的字段中去
字符集(也称字元集,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是国家字符集。
数据库的字符集在建立数据库的时候创建。目前也有方法转换字符集,但两个字符集的转换还是存在风险,造成数据丢失或错误,不建议使用。
2, Oracle Client字符集(NLS_LANG)
在访问Oracle的客户端安装Oracle Client过程中并没有选项选择Oracle Client的字符集,安装完毕后在注册表HKLOCAL_MACHINE\SOFTWARE\ORACLE\KEY_ORACLECLENT_HOME1\可以找到NLS_LANG键,值为当前OS的字符集。如简体系统为:ZHS16GBK,繁体系统为:MSWIN950。可见,Oracle Client(以下简称NLS_LANG)在安装过程中选择了OS的字符集作为默认的NLS_LANG字符集。
设定NLS_LANG有三种方法:
a) 修改注册表。将HKLOCAL_MACHINE\SOFTWARE\ORACLE\KEY_ORACLECLENT_HOME1\下NLS_LANG键值改为你要设定的字符集,如将SIMPLIFIED CHINESE_CHINA.ZHS16GBK改为:SIMPLIFIED CHINESE_CHINA.AL32UTF8。但这种做法似乎无效,即使重新启动机器后,也没有生效,NLS_LANG仍使用当初安装时的OS字符集。
b) 设定环境变量。在My Computer->Properties->Advanced->Environment Variables->System Variables 新增环境变量设置,如:Variable name=NLS_LANG,Variable Value= SIMPLIFIED CHINESE_CHINA.AL32UTF8。这样NLS_LANG字符集为UTF8,这个NLS_LANG优先序高于注册表中的NLS。注意:环境变量设在系统变量中(System Vairables),而不是用户变量(User Vairables)。
c) 在应用程序运行的Process Session中设定。在程序运行之前,先通过set NLS_LANG=进程Session的字符集。例如:
Echo %nls_lang%,在这个session中,已经设定NLS_LANG字符集为ZHS16GBK。同样,你也可以新开一个CMD窗口,设定另一种NLS_LANG字符集。这种在session中设定NLS_LANG的优先序高于系统环境变量NLS_LANG。注册表NLS_LANG、系统环境变量NLS_LANG、Session NLS_LANG的优先序是:Session NLS_LANG > 系统环境变量NLS_LANG > 注册表NLS_LANG。
三、Oracle数据库如何存储多国文字
首先,先看一个有趣的问题。我们要保存的文字哪里来?一种方法是在屏幕上输入,输入中文时,我们打开自己习惯的输入法,在应用程序给你提供的输入框内输入文字;还有一种方法是复制粘贴的方法,将文字从网页、文档中拷贝后再粘贴到输入框中,那问题是:输入框中的文字使用的字符集是什么?有人说,是客户端操作系统的默认字符集。好,我的操作系统是简体中文,默认系统字符集是GB2312,在输入框中输入韩文字符“삼성”,如果这两个韩文字符是用GB2312字符集解码的,输入框内应该显示两个“?”,因为GB2312字符集内没有韩文字符只能用“?”代替。但是现在这两个韩文字符在输入框内正常的显示,说明这两个韩文的字符集是支持韩文字符的字符集,是韩文字符集“euc-kr”,还是Unicode字符集?肉眼看不出来,也许查看一下内存中输入框中文字的编码能找到答案,喜欢钻研的人可以去看一看。表面来判断,可能是根据输入法使用的字符集,输入法使用什么样的字符集,输入的文字就是用的什么样的字符集。从网页上复制粘贴过来的文字,应该跟网页的字符集是一致的。其实,我们不关心多国文字背后的字符集是用的本国字符集还是unicode字符集,我们关心的是多国文字如何在数据库中被正确地存取。
以oracle 10g R2 10.2.0.3 作为测试数据库版本,在数据库建立一张表:
表名称:mer_categ,商品类别表
字段
数据类型
长度
说明
S_merc_id
Varchar2
20
分类编号
S_merc_name
Varchar2
50
分类名称
现在要新增一个分类编号为01,分类名称为“삼성”的记录。即使SQL的初学者也会写出:
Insert into mer_catag values (‘01’,’삼성’);
这条SQL语句没有错,但是能不能把“삼성”正确的写入数据库,仅仅靠一条SQL语句是不够的,在分析各种测试环境之前,我们看一段官方关于SQL语句中字符串字符编码的描述:
“Being part of a SQL or PL/SQL statement, the text of any literal, with or without the prefix N, is encoded in the same character set as the rest of the statement. On the client side, the statement is in the client character set, which is determined by the client character set defined in NLS_LANG, or specified in theOCIEnvNlsCreate() call, or predefined as UTF -16 in JDBC. On the server side the statement is in the database character set.”
这段话告诉我们:SQL语句提交到Server之前,SQL语句中的字符串部分(不管前面有没有N’)作为语句的一部分将被用NLS_LANG定义的字符集进行编码。提交到Server端后,再被数据库字符集编码。可以推出:如果数据库字符集与客户端NLS_LANG字符集一致,在Server端就没有必要再一次编码了。
在安装oracle数据库时如果一直选择“下一步”,数据库字符集将默认使用操作系统字符集。如在简体OS下,安装Oracle Server,创建Oracle实例后,实例的数据库字符集默认是ZHS16GBK;安装客户端后,NLS_LANG默认是ZHS16GBK字符集。GBK是汉字大字符集,处理汉字简繁体都可以,所以平时使用类似:
Insert into mer_catag values (‘01’,’中国’);
Insert into mer_catag values (‘01’,’中國’);
都是正常的。但是当处理多国文字时,就不灵了。如:
Insert into mer_catag values (‘01’,’삼성’);
根据前面引用的官方描述,这条SQL语句无论是字符串部分还是其他部分,将先被NLS_LANG定义的字符集转换,“삼성”将用GBK字符集转换,前面讲过,“삼성”转换后的字符是“??”(两个全角问号)。SQL语句变成了:
Insert into mer_catag values (‘01’,’??’);
在server端,因数据库字符集与NLS_LANG一致,SQL语句不再进行字符集转换,执行SQL后,数据库存储了两个全角“?”。用select dump(s_merc_name,16) from mer_categ验证一下,得到结果是:Typ=1 Len=4: a3,bf,a3,bf。“a3,bf”就是全角”?”的GBK编码。两个韩文字符被当作”?”存在了数据库中,查询出的当然也是”?”。所以,不对oracle字符集进行配置,不能正确处理多国文字的存储。
客户端的NLS能实现对多国文字进行正确字符集转换的话,毫无疑问是选择Unicode字符集。用set NLS_LANG =SIMPLE CHINESE.AL32UTF8可以修改客户端的NLS为UTF8字符集,还是以
Insert into mer_catag values (‘01’,’삼성’);
为例,在客户端,这条SQL语句使用UTF8字符集做了编码转换,韩文字符“삼성”的编码转为:“ec-82-bc,ec-84-b1”(UTF8编码)。下一步,关键看Server端的数据库字符集了,如果数据库字符集仍为GBK,也就是说,“삼성 ”要作UTF8->GBK的转码,能转成功吗?显然不可以,连个韩文字符又被全角“?”代替了。在server端,SQL语句被转成了:
Insert into mer_catag values (‘01’,’??’);
数据库又存了两个全角“?”。怎么办?Server端能不能不作字符集转换?前面提到,如果数据库字符集与客户端NLS_LANG字符集一致,在Server端就没有必要再一次编码了。好,那就在Server端将数据库字符集设为UTF8,韩文字符“삼성”就以UTF8的字符编码存到数据库里了。验证一下,select dump(s_merc_name,16) from mer_categ,结果是:Typ=1 Len=6: ec,82,bc,ec,84,b1。这个结果与前面看到的UTF8编码是一致的。所以,当数据库字符集与NLS_LANG(客户端)都设为UTF8字符集时,可以解决多国文字正确存储的问题。
似乎将数据库字符集与NLS_LANG都设为UTF8的做法未得到广泛应用,原因是大多数的应用不存在使用多国语言的问题?没做过相关调查。除此之外,使用UTF8存储数据占用更多的空间是事实存在的,一个汉字字符UTF8使用三个字节存储,而在GBK中使用两个字节,用GBK作为数据库字符集存储汉字更经济实惠些。最后,任何存入数据库的数据都先经过UTF8的转码再存储,必然带来效能的损失。那能不能区别对待存储的数据呢?例如只针对存在多国字符的数据使用Unicode字符集存储呢?这就是国家字符集(National Chartset)存在的原因。国家字符集是那些存放在NCHAR,NVARCHAR2,NCLOB字段中的数据的Unicode字符编码集,Oracle 10g使用AL16UTF16字符集作为默认的数据库国家字符集。如何将多国文字存储到NVARCHAR2这样的字段中去
发表评论
-
oracle_plsql配置tnsnames.ora不对
2013-03-05 16:06 968plsql tnsnames.ora 配置不对, 方法二: ... -
win8永久激活工具
2012-11-07 15:21 0【精华】【旭日东升】w ... -
Windows 7上成功安装Oracle 10g的一点经验[转]
2012-12-28 09:22 666Windows 7上成功安装Oracle ... -
10g以后Oracle不支持ZHS32GB18030[转]
2012-12-28 09:21 772在9i中Oracle存在字符集ZH ... -
oracle安装中遇到的问题 修改计算机名后不能连接[转]
2012-12-28 09:21 551oracle安装中遇到的问题 修改计算机名后不能连接 博客分 ... -
SQL查询练习题(oracle)[转]
2012-12-28 09:21 1114SQL查询练习题(oracle) 博客分类: Oracle数 ... -
Oracle原理笔记(待续)[转]
2012-12-26 09:04 581Oracle原理笔记(待续) 博客分类: Oracle数据库 ... -
Oracle的JDBC驱动的版本你了解吗?[转]
2012-12-26 09:04 654Oracle的JDBC驱动的版本你 ... -
11月导入数据库记录(oracle),查最大连接数等.[转]
2012-12-31 09:01 63711月导入数据库记录(orac ... -
Oracle数据库的导入导出[转]
2012-12-31 09:01 721Oracle数据库的导入导出 博客分类: Oracle数据库 ...
相关推荐
### Oracle数据库多语言文字存储解决方案 #### 一、字符集概念及重要性 在计算机科学领域,字符集(Character Set)是指一系列字符与特定编码方式之间的映射规则。它定义了如何将字符转换为计算机能够识别的二进制...
Oracle 数据库多语言入库问题的解决方案是针对企业在国际化进程中遇到的多国语言信息存储难题,尤其是在使用Oracle数据库时,由于字符集的不兼容性导致非中文语言数据入库时出现乱码。Oracle数据库作为全球广泛使用...
【Oracle数据库大作业】是一个关于Oracle数据库在教务管理系统中的应用项目,可能涵盖了数据库设计、实施、优化等多个方面的内容。这个大作业包含了PPT演示文稿、Word文档以及可能的源代码,为学习者提供了全面了解...
Oracle 数据库字符集问题解决方案大全 Oracle 数据库字符集问题解决方案大全中,提出了 Oracle 数据库汉字显示异常的解决方案。该文档涵盖了字符集的概念、字符集的设置、字符集的影响因素、解决汉字显示异常的...
Oracle数据库以其高效、稳定和强大的功能在金融、电信、医疗、政府等多个领域得到广泛应用。本资料大全将围绕Oracle数据库的核心概念、管理和优化等方面进行深入探讨。 一、Oracle数据库基础 Oracle数据库系统基于...
学习Oracle数据库,通常需要掌握基本的PL/SQL语法,这是Oracle的内置过程语言,用于编写存储过程、函数和触发器。同时,理解Oracle的性能监控工具(如AWR和ASH报告),以及如何使用Explain Plan分析SQL执行计划,...
Oracle数据库系统由Oracle公司开发,提供了一整套解决方案,包括数据库服务器、数据存储、备份恢复、安全管理等。其核心功能是存储、管理和检索数据,支持多用户并发访问,并具备高度的可扩展性和可靠性。 二、...
在IT行业中,数据库管理是至关重要的任务之一,尤其是在存储非结构化数据如图片时。本话题聚焦于如何批量导入图片到Oracle数据库,这是一种常见的需求,...通过理解和实践,你可以创建高效且可靠的图片存储解决方案。
Oracle数据库实用教程主要涵盖了Oracle数据库系统的基础知识、安装配置、数据管理、SQL查询、数据库安全性、性能优化以及备份恢复等多个方面。以下是对这些知识点的详细解释: 1. **Oracle数据库介绍**:Oracle...
Oracle数据库系统是一种支持分布式处理、高度可扩展、安全可靠的数据库解决方案。它采用SQL(结构化查询语言)作为其主要的数据操作和查询语言,并提供了丰富的数据类型、存储过程、触发器等特性。 2. **安装与...
Oracle数据库系统是全球广泛使用的大型关系型数据库管理系统之一,它为数据存储、管理和处理提供了高效、安全和可扩展的解决方案。对于初学者来说,理解Oracle数据库系统应用与开发的基础至关重要,这将帮助他们掌握...
Oracle数据库系统是全球广泛使用的大型关系型数据库管理系统之一,它为各类企业和组织提供了高效、安全的数据存储和管理解决方案。这个《Oracle数据库系统》多媒体课件是深入学习Oracle技术的宝贵资源,涵盖了从基础...
此外,"疑难解析"的部分暗示了书中会包含一些实战案例和常见问题的解决方案,例如处理锁定和死锁,排查性能瓶颈,解决并发问题,以及如何在Oracle数据库中处理大数据量的挑战。这些问题的解决经验对于提升数据库管理...
Oracle数据库比对工具是一款专为Oracle数据库设计的实用软件,由Delphi编程语言编写并提供源码,使得用户可以深入理解其工作原理并根据需要进行定制。在数据库管理、迁移、整合或性能优化等场景中,这样的工具能帮助...
在Oracle数据库管理中,字符集的设置至关重要,它直接影响到数据的存储、检索以及与之交互的准确性。本文将深入探讨Oracle数据库字符集的概念、重要性、修改过程及其潜在问题,特别是当尝试修改数据库字符集时遇到的...
"LIB图书管理系统"就是这样一款利用Java编程语言与Oracle数据库相结合,旨在提升图书管理效率,优化服务流程的高效解决方案。下面我们将详细探讨该系统中的关键技术及其应用。 一、Java技术 Java作为一种跨平台的...
### Oracle数据库日常维护方案知识点详解 ...综上所述,Oracle数据库日常维护方案涵盖了性能优化、备份恢复、运维管理等多个方面,旨在全面提升Oracle数据库的稳定性和响应速度,为企业信息化建设提供坚实的支撑。
Oracle数据库不仅提供了丰富的功能,还支持多种操作系统和硬件平台,使其成为许多企业的首选数据库解决方案。这份“Oracle数据库技术”的资料旨在帮助初学者快速掌握Oracle的核心概念和技术。 首先,Oracle数据库的...
Oracle数据库是由甲骨文公司开发的,提供了一整套数据存储、管理和检索解决方案。它支持多种操作系统和硬件平台,具有高可用性、高性能和安全性等特性。Oracle数据库采用SQL作为查询语言,同时支持PL/SQL进行过程化...