[转]oracle国家字符集与数据库字符集

服务器端:(oracle服务器端字符集)
数据库字符集在创建数据库时指定,在创建后通常不能更改。在创建数据库时,可以指定字符集(CHARACTER SET)和国家字符集(NATIONAL CHARACTER SET)。
1. 字符集:
    (1)用来存储CHAR, VARCHAR2, CLOB, LONG等类型数据
    (2)用来标示诸如表名、列名以及PL/SQL变量等
    (3)用来存储SQL和PL/SQL程序单元等
2. 国家字符集:
    (1)用以存储NCHAR, NVARCHAR2, NCLOB等类型数据
    (2)国家字符集实质上是为oracle选择的附加字符集,主要作用是为了增强oracle的字符处理能力,因为NCHAR数据类型可以提供对亚洲使用定长多字节编码的支持,而数据库字符集则不能。国家字符集在oracle9i中进行了重新定义,只能在unicode编码中的AL16UTF16和UTF8中选择,默认值是AL16UTF16
3. 查询字符集参数:
    可以查询以下数据字典或视图查看字符集设置情况
    nls_database_parameters、props$、v$nls_parameters
    查询结果中NLS_CHARACTERSET表示字符集,NLS_NCHAR_CHARACTERSET表示国家字符集
4. 修改数据库字符集:
    按照上文所说,数据库字符集在创建后原则上不能更改。如果需要修改字符集,通常需要导出数据库数据,重建数据库,再导入数据库数据的方式来转换,或通过ALTER DATABASE CHARACTER SET语句修改字符集,但创建数据库后修改字符集是有限制的,只有新的字符集是当前字符集的超集时才能修改数据库字符集,例如UTF8是US7ASCII的超集,修改数据库字符集可使用ALTER

客户端:(NLS_LANG参数)
客户端字符集定义了客户端字符数据的编码方式,任何发自或发往客户端的字符数据均使用客户端定义的字符集编码,客户端可以看作是能与数据库直接连接的各种应用,例如sqlplus,exp/imp等。客户端字符集是通过设置NLS_LANG参数来设定的。

国家字符集的不同:(AL16UTF16与UTF-8)
1. AL16UTF16 和 UTF8 这两种选择都适用于国家字符集
2. AL16UFT16 是宽度固定的双字节 Unicode 字符集;UTF8 是宽度可变的、一至三个字节的 Unicode 字符集
3. 欧洲字符在 UTF8 中按一至两个字节存储,而在 AL16UTF16 中按两个字节存储,相比之下,UTF8可以节省空间;亚洲字符在 UTF8 中按三个字节存储,这样,所需的空间比在 AL16UTF16 中要多
4. AL16UTF16 是宽度固定的编码,因此在执行速度上要比宽度可变的 UTF8 快

如果使用EXP/IMP进行数据库的导出/导入,不仅要注意两服务器端之间的字符集的兼容性,而且要考虑到导出/导入过程中,服务器端与客户端之间的字符集的兼容性,特别是导出的时候。

 

 

第一部分字符集与编码常识

字符集:

人们根据需要把某些字符收集到一处,并赋以名称,于是便有了某某字符集。

编码:

前面收集的工作完成以后,为了让只认识数字的“愚蠢”的计算机也能够存储字符,人们不得不为集合里的每一字符分配身份证号码,这就是编码,从此,终于可以以存储编码的方式在计算机中存储字符了。

在字符集与编码世界的漫漫历史长河里(伪),出现过若干个让计算机工作者们如雷贯耳的名字,这些名字,有些已经成了浮云飘散了,有些还在我们的代码中折腾。

ASCII

ü ASCII字符集:包含大小写英文、阿拉伯数字、标点,以及一些不可见的控制符共128个。

ü ASCII编码:使用7位表示一个字符。编码范围是[0-127](即Hex[00-7F]),其中[0-31]Hex[00-1F])部分以及127Hex7F)是控制符,其余的都是些可见字符。

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 pageOEM 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 XPANSI code page=1252, OEM code page=437

PC 2:中文版Windows 7ANSI code page=936,   OEM code page=936

PS2cp1252cp437编码表下载请猛击这里,早期控制台应用程序常常需要画一些粗糙的表格等等图形,所以可以在437中看到不少不同的横线竖线这一类的特殊符号。

PS3CP1252ISO8859-1ASCII比较,就实际使用的编码范围来说:CP1252>ISO8859-1>ASCIIASCII[0-127]CP1252[0-255]ISO8859-1则移除了cp1252[0-31]127这些不可见的控制符,同进移除了[128-159](即Hex[80-9F])中的特殊符号。

第二部分 Oracle中的编码与字符集

1.为什么需要两个字符集?

Oracle中有两个字符集:

1)数据库字符集

2)国家字符集

为什么要有两个字符集?如果我知道只需要英文,设置数据库字符集=US7ASCII,如果我知道只需要西欧字符,设置数据库字符集=WE8MSWIN1252或者WE8ISO89859P1,或者干脆就用AL32UTF8。你看,我只需要设定“数据库字符集”,那么“国家字符集”有什么必要呢?

其实,考虑到历史遗留问题以及数据库创建者们无法避免的“短视”,很多现有数据库都无法支持UNICODE字符集,例如要在现有的US7ASCII数据库字符集的数据库中存储中文,这个时候“国家字符集”+NVARCHAR2这样的组合就能救你一命了。对于数据类型为NVARCHAR2(以及NCHAR, NCLOB)的字段,它使用是国家字符集,与数据库字符集的设置无关。自9i以后,国家字符集可选的只有AL16UTF16AL32UTF8UTF-16UTF-8都是UNICODE编码标准的实现,因些可以表示世界上几乎所有的文字。

当然,如果数据库字符集本身就使了UNICODE字符集,就没有必要使用NVARCHAR2, NCHAR, NCLOB这些类型了。

2.字符集名称的玄机

Oracle对字符集的命名实际上有一定的规则可寻,例如:

AL32UTF8

AL】支持所有语言(All Language)。

32】每字符最多占用32位(4字节)。

UTF8】编码为UTF-8

WE8MSWIN1252

WE】支持西欧语言(Western Europe)。

8】每字符需要占用8位(单字节)。

MSWIN1252】编码为CP1252

US7ASCII

US】表示美国(United States)。

7】每字符需要占用7位。

ASCII】编码为ASCII

其它如ZHS16GBKZHT16BIG5US8PC437(编码为OEM cp437),都可以类推。

Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。

UTF-8以字节为单位对Unicode进行编码。从Unicode到UTF-8的编码方式如下:

Unicode编码(16进制) 
UTF-8 字节流(二进制)
000000 - 00007F
0xxxxxxx
000080 - 0007FF
110xxxxx 10xxxxxx
000800 - 00FFFF
1110xxxx 10xxxxxx 10xxxxxx
010000 - 10FFFF
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

 

SELECT TO_NUMBER(369,'XXX') FROM DUAL;

SELECT NLS_CHARSET_NAME(873) FROM DUAL;

SELECT NLS_CHARSET_ID('AL32UTF8') FROM DUAL;

SELECT * FROM v$nls_valid_values WHERE PARAMETER = 'CHARACTERSET';

猜你喜欢

转载自buralin.iteye.com/blog/1948047