1 字符集超集 当一种字符集(字符集A)的编码数值包含所有另一种字符集(字符集B)的编码数值,并且两种字符集相同编码数值代表相同的字符时,则字符集A是字符集B的超级,或称字符集B是字符集A的子集。
Oracle有子集-超级对照表(subset-superset pairs),例如WE8ISO8859P1、ZHS16CGB231280、ZHS16GBK都是US7ASCII的超集。
2 国家字符集(National character set)
国家字符集用以存储NCHAR, NVARCHAR2, NCLOB等类型数据,只能在unicode编码中的AF16UTF16和UTF8中选择,默认值是AL16UTF16。
3 数据库字符集(national character set)
Oracle中个,如下三个场景,需要使用到数据库字符集。
●存储CHAR, VARCHAR2, CLOB, and LONG类型的数据
●识别表名、列名、PL/SQL变量等
●输入和存储SQL和PL/SQL源码
由于字符集需要用来识别SQL和PL/SQL代码,所以oracle的字符集必须是ASCII或EBCDIC【EBCDIC是为IBM推出的字元编码表,地位与ASCII对应】的超集。所以Oracle字符集不能使多字节定长编码字符集,例如AL16UTF16【AL16UTF16是定长2字节编码】。在不考虑EBCDIC情况下,Oracle的字符集一定是ASCII的超集,比如字符'a'在ASCII中的编码是0x61,在数据库字符集中的编码也要是0x61。
4 Oracle中的字符集格式和常见的字符集
oracle中字符集的命名格式:
[S|C]
region: zhs表示中文简体,zht表示中文繁体,us美国英语,we表示西欧语言,eg表示英语.
最后一个字段:S 只对server有效;C表示只对client有效。
oracle中常见的字符集名称格式
Oracle Character Set Name
Description
Region
Number of Bits Used to Represent a Character
Standard Character Set Name
US7ASCII
SB, ASCII
US
7
ASCII
WE8ISO8859P1
SB, ASCII
WE (Western Europe)
8
ISO8859 Part 1
ZHS16GBK
MB, ASCII,UDC
中国大陆(中文简体)
16
GBK
ZHT16BIG5
MB, ASCII
台湾
16
BIG5
AL32UTF8
MB,ASCII,EURO
UTF-8
ZHS16CGB231280
MB,ASCII
中国大陆(中文简体)
16
GB231280
Unicode字符集
Name
Description
Comments
AL16UTF16
Unicode 4.0 UTF-16 Universal character set
定长,2个字节编码(疑问:UTF-16可能占用2byte,也可能占用4byte,在oracle中为什么是定长的?)。只能作为国家字符集码
MB, EURO, FIXED
AL32UTF8
Unicode 4.0 UTF-8 Universal character set
MB, ASCII, EURO
UTF8
Unicode 3.0 UTF-8 Universal character set, CESU-8 compliant
MB, ASCII, EURO
UTFE
EBCDIC form of Unicode 3.0 UTF-8 Universal character set (UTF-EBCDIC)
MB, EURO
表中的简写
SB: single-byte encoding 单字节编码
MB: multibyte encoding 多字节编码
FIXED: fixed-width multibyte encoding 定长编码
ASCII: strict superset of ASCII ASCII的超集
EURO: euro symbol supported 支持欧元符号
UDC: user-defined characters supported 支持用户自定义的字符
AL32UTF8与UTF8区别:
AL32UTF8对应Unicode4.0,UTF8对应Unicode3.0。Unicode4.0在Unicode3.0基础上增加了一些字符,但是在实际当中,使用到这些新增字符的可能性非常小,因此绝大部分情况下,选择UTF8也是足够的。
而对于数据库的访问而言,二者还是存在一定差异的。前面提到了AL32UTF8字符集是9i才出现的,那么对于9i以后的版本访问没有任何问题,但是对于8i及以前的版本,则不认识这个字符集。这就使得8i及更低版本的客户端在访问9i以上AL32UTF8的数据库时,会碰到各种各样的问题。因此,Oracle建议在选择AL32UTF8和UTF8字符集时,最关键的一点就是是否有8i及以下版本的客户端会登录到数据库中,如果没有则可以选择AL32UTF8,如果存在这种客户端,那么需要选择UTF8字符集。
5 长度的语义
--最多存储10个字节的数据
VARCHAR2(10 BYTE)
--最多存储10个字符,存储可能超过10个字节。
VARCHAR2(10 CHAR)
--取决于参数NLS_LENGTH_SEMANTICS,如果值为BYTE ,语句与VARCHAR2(10 BYTE)等价;如果值为CHAR,则语句与VARCHAR2(10 CHAR)等价
VARCHAR2(10)
建议使用ORACLENLS_LENGTH_SEMANTICS指定的语义,避免相同数据库出现不同的长度语义。
6 数据库字符集转换
如果oracle客户端和服务端的字符集不同,Oracle Net会自动在两者之间进行转换,转换对用户是透明的。例如:'你'的GBK编码是0xc4e3,UTF8编码是0xe4bda0,我们假设服务端字符集是AL32UTF8,客户端的字符集是ZHS16GBK, 客户端向类型为varchar2的类写入'你',则Oracle net收到的数据是oxc4a3,Oracle Net检测到客户端和服务端的字符集不同,于是发生转换,最终写入dbf文件的是数据0xe4bda0。可以通过dump函数来验证。
字符集转换有如下两个缺点:
●可能造成数据的改变
只要其中的一个字符集不能对另外一个字符集的某个字符不能编码时,就可能出现有损转换,即数据被改变。注意,有损转换在读数据和写数据都有可能发生。
●影响服务端的性能
为了避免数据的改变,服务端的字符集【记为A】 必须 覆盖 其所有客户端的字符集【记为B】,即A必须对B中每个字符都能够编码。A为WE8ISO8859P1,B为S7ASCII,符合要求。反之,A为US7ASCII,B为WE8ISO8859P1不符合要求,比如客户端写字符"'?',由于ASCII无法表示这个字符,OracleNet把这个字符转化为'?'。
注:在Oracle官网指明服务端的字符集一定要是客户端字符集的超集,我认为是不对的。我认为服务端的字符集能够对客户端的每个字符都能编码即可。也有可能我对oracle文档中的supserset理解有误。
图 字符集转换出现异常的例子,由于US7ASCII不能对
WE8MSWIN1252中的每个字符进行编码,所以可能出现有损转换
图 字符集不会出现异常的例子,前提是客户端只读取自己提交
的数据,如French Client读取 Japanese Client(JA16EUC)的
数据,也可能出现数据的有损转换。
Oracle建议客户端和服务端的字符集最好保持一致。
7 数据库字符集选取
oracle强烈建议使用Unicode字符集,因为Unicode字符集提供很好的可用性、兼容性、可扩张性。
8 服务端字符集的查看和修改
●修改
在不重建数据库的条件下,数据库字符集在数据库创建后原则上不能更改。只有一个例外:只有新的字符集是当前字符集的严格超集时才能修改数据库字符集,例如UTF8是US7ASCII的超集,修改数据库字符集可使用如下语句。
alter database character set utf8;
●查看
通过视图v$nls_parameters可以查看字符集。其中NLS_CHARACTERSET表示数据库字符集,NLS_NCHAR_CHARACTERSET表示国家字符集。
select * from v$nls_parameters;
select userenv('language') from dual;
9 客户端字符集的设置
客户端字符集是通过设置NLS_LANG参数来设定的。 NLS_LANG参数格式如下:
NLS_LANG = LANGUAGE_TERRITORY.CHARACTER_SET
Parameter
Description
LANGUAGE
显示oracle消息,校验,日期命名
TERRITORY
指定默认日期、数字、货币等格式
CHARACTER_SET
指定客户端将使用的字符集
例如:
NLS_LANG=AMERICAN_AMERICA.US7ASCII
AMERICAN是语言,AMERICA是地区,US7ASCII是客户端字符集
NLS_LANG常见的值:
Chinese
(PRC)
SIMPLIFIED CHINESE_CHINA.ZHS16GBK
Chinese
(Taiwan)
TRADITIONAL CHINESE_TAIWAN.ZHT16MSWIN950
English
(United Kingdom)
ENGLISH_UNITED KINGDOM.WE8MSWIN1252
English
(United States)
AMERICAN_AMERICA.WE8MSWIN1252
Japanese
JAPANESE_JAPAN.JA16SJIS
客户端字符集设置主要方法
●UNIX环境
$NLS_LANG="simplified chinese"_china.zhs16gbk
$export NLS_LANG
编辑oracle用户的profile文件
●Windows环境
编辑注册表
HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOMEID\NLS_LANG
客户端修改字符集的方法
●修改环境变量NLS_LANG
●使用ALTER SESSION语句,在oracle会话中修改
●使用某些SQL函数
优先级是:Sql function > alter session > NLS_LANG