ASCII:
ü ASCII字符集:包含大小写英文、阿拉伯数字、标点,以及一些不可见的控制符共128个。
ü ASCII编码:使用7位表示一个字符。编码范围是[0-127](即Hex[00-7F]),其中[0-31](Hex[00-1F])部分以及127(Hex7F)是控制符,其余的都是些可见字符。 GB2312:
ü GB2312字符集:ASCII字符集+7000左右汉字字符。
ü GB2312编码:兼容ASCII编码。对字节进行判断,如值<=127,则意义等同于ASCII编码;如值>127,则它需要跟其后的另一个字节合并表示一个字符。其理论汉字编码空间为128X256,超过3万个字符。 GBK:
ü GBK字符集:GB2312字符集+20000左右汉字字符。
ü GBK编码:兼容GB2312编码。利用了GB2312编码闲置的编码空间。 GB18030:
ü GB18030字符集:GBK字符集+若干汉字+若干少数民族字符,为目前国内最新的字符集。
ü GB18030编码:兼容GBK编码。继续利用GBK编码闲置的编码空间,对于超出编码空间的则采用4个字节表示。 BIG5:
ü BIG5字符集:ASCII字符集+13000左右汉字(繁体)。
ü BIG编码:兼容ASCII编码。其编码模式类似于GB2312. UNICODE:(UNICODE一词在日常使用中显得宽泛、混乱,在不同的语境中可以是以下意思之一。)
ü UNICODE标准:由一些组织提出的一套标准,对人类文字的显示、编码等进行了一系列的规定。
ü UNICODE字符集:目前最新版的UNICODE字符集中已经包含各种语言的超过10万的字符。
ü UNICODE编码:(狭义的UNICODE编码可能指UCS-2,也可能指UTF-16;广义的UNICODE编码可以指包括以下四种在内的若干种对UNICODE标准的编码实现。)
1. UTF-32编码:固定使用4个字节来表示一个字符,存在空间利用效率的问题。
2. UTF-16编码:对相对常用的60000余个字符使用两个字节进行编码,其余的(即’补充字符supplementary characters’)使用4字节。
3. UCS-2编码:是对UNICODE早期版本的实现,它与UTF-16的唯一区别是它不包括’补充字符’,所以它对字符的编码只使用两个字节。目前此编码模式已过时。
4. UTF-8编码:兼容ASCII编码;拉丁文、希腊文等使用两个字节;包括汉字在内的其它常用字符使用三个字节;剩下的极少使用的字符使用四个字节。 ISO8859-1:(使用Oracle的同志们可能见过这个WE8ISO89859P1,没错,就是它。)
ü ISO8859-1字符集:ASCII字符集+若干西欧字符,例如字母Â、Ë。
ü ISO8859-1编码:使用8位表示一个字符,同时移除了原ASCII编码中的控制符(即[0-31],及127)。 Code page:(可以把”code page”认为是”编码”的近义词。至于为什么有这个名称?历史遗留问题。)
ü ANSI code pages:你一定见过ANSI,想想另存文本文件时。ANSI code pages实际上是一系列的编码集合,根据操作系统区域设置而激活其中一种作为默认ANSI编码。例如公司电脑(英文系统)上的ANSI code page可能是1252,而家里的中文系统则可能是936。所以在家里可以用ANSI存储一个包含中文的文本文件,在公司则不行。可以在注册表键:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\NLS\CodePage\ACP中查看到当前使用的ANSI code page。 C#可以通过Encoding.Default查看。
ü OEM code pages: OEM code pages是给控制台应用程序(如SQLPLUS)使用的。除CJK环境(Chinese-Japanese-Korean)外,Windows使用不同的ANSI code page和OEM code page。例如,公司英文系统上使用的是437。可以使用CHCP命令查看当前使用的OEM code page, C#可以通过Console.OutputEncoding查看。 Code page 1252:
ü cp1252字符集:ASCII字符集+若干西欧字符+若干特殊符号,比如™、‰.
ü cp1252编码:使用8位表示一个字符。编码范围是[0-255](即Hex[00-FF]),[0-127]部分与ASCII相同,新增的大部分是西欧的字符,例如一些带上标的字母Â、Ë,以及像这样一类特殊符号)
PS1:现实中两台PC上的code page信息
PC 1:英文版Windows XP,ANSI code page=1252, OEM code page=437
PC 2:中文版Windows 7,ANSI code page=936, OEM code page=936 PS2:cp1252与cp437编码表下载请猛击这里,早期控制台应用程序常常需要画一些粗糙的表格等等图形,所以可以在437中看到不少不同的横线竖线这一类的特殊符号。 PS3:CP1252、ISO8859-1、ASCII比较,就实际使用的编码范围来说:CP1252>ISO8859-1>ASCII。ASCII是[0-127],CP1252是[0-255],ISO8859-1则移除了cp1252中[0-31]及127这些不可见的控制符,同进移除了[128-159](即Hex[80-9F])中的特殊符号。
3.例子很重要 3.1.准备两个数据库
上帝说要有例子,于是有了两个相同版本的数据库,A跟B:
3.2.工具很重要
View Code SELECT parameter, VALUE
FROM nls_database_parameters
WHERE parameter IN ('NLS_CHARACTERSET', 'NLS_NCHAR_CHARACTERSET')
--数据库A:
PARAMETER VALUE
------------------------------ -------------------
NLS_CHARACTERSET WE8MSWIN1252
NLS_NCHAR_CHARACTERSET AL16UTF16
--数据库B:
PARAMETER VALUE
------------------------------ -----------------
NLS_CHARACTERSET AL32UTF8
NLS_NCHAR_CHARACTERSET AL16UTF16
在测试之前,为避免工具本身的特性给人造成的困惑,介绍一下几个客户端工具对UNICODE 的支持情况:
ü SQLPLUS:不支持UNICODE字符集。是否支持中文取决于当前的OEM code page,如果是cp437,无论输入还是显示中文都是不可能的。但如果是cp936,则可以支持中文输入输出。
ü PLSQL Developer:7.0版本的查询结果窗口支持UNICODE字符集,但是编辑窗口(即输入SQL语句的窗口)不支持。8.0版完全支持UNICODE。
ü Oracle SQL Developer:查询结果窗口与编辑窗口都支持UNICODE字符集。
ü 客户端操作系统不支持显示中文。
ü Oracle客户端工具(这里是Oracle SQL Developer)不支持显示中文。
ü Oracle客户端有相关设置(比如NLS_LANG)不正确。
ü 存储在数据库中的数据已经是不正确的数据。
第一点,客户端操作系统是否支持中文对运行于其上的应用程序有影响吗?应该有两种情况,一种是应用程序依赖于操作系统的中文支持;另一种是有一些软件自己带有语言包及字体(比如Adobe的一些产品,.NET程序在编译的时候也可以选择将字体文件打包进去),那么它应该不依赖于操作系统。
我猜测Oracle SQL Developer应该是属于前一种,同时我检查了操作系统,确定其已经支持东亚语言(Control panel—Regional and language options—Language tab—Supplemental languages support—Install files for East Asian languages,如果checkbox已经选中,说明已经安装东亚语言包)。
第二点,无论查询结果窗口还是编辑窗口都支持UNICODE字符集。
第三点,由于不依赖于Oracle client的OCI,客户端注册表中的NLS_LANG设置对像Oracle SQL Developer没有影响。
第四点,我们借助DUMP()函数来确定NVARCHAR2字段中具体的内容。
DUMP()的语法:DUMP(<value>[,<format>[,<offset>[,<length>]]])
其中的format参数:如果是8则表示结果使用8进制表示,如果是16则表示16进制,如果是0到16间的其它数则都使用10进制。如果是大于16的数,则分几种情况:如果是可见的ASCII字符则直接打印此字符,如果是控制字符则打印成“^x”,其它情况则把结果按16进制显示。为format加上1000则表示除了输出结果之外,还会附带输出所使用的字符集信息。
这里我们使用:我们知道“中”字的UTF-16编码是4E2D,显然在A库中存储的数据已经是不对的,00BF实际上就是一个倒的问号字符,其存储在数据库中的原始数据已经不对了,更何况是客户端的显示。