Oracle关于字符集的分析
字符集有很多种,最初出现的字符集是ASCII,由于ASCII支持的字符数很有限,因此随后又出现了很多的编码方案比如Unicode。 Unicode是一个涵盖了目前全世界使用的所有已知字符的单一编码方案,其中常见的UTF-16是unicode的16位编码方式,是一种定长多字节编码;而UTF-8是unicode的8位编码方式,是一种变长多字节编码。
GBK和UTF-8是最常见到的两种字符编码方案,其中GBK是一个简体中文字符集的中国国家标准,是在国家标准GB2312基础上扩容后兼容GB2312的标准,包含全部中文字符,是GB2312的扩展,主要用于汉字编码;而UTF-8是用以解决国际上字符通用的一种多字节编码,包含全世界所有国家需要用到的字符,可以在各国各种支持UTF8字符集的浏览器上显示,是全世界通用的;ZHS16GBK按照2个字符长度存储一个汉字。UTF8字符集是多字节存储,1个汉字有时采用3个字符长度存储。
当字符集 A的编码数值包含字符集 B的编码数值,并且两种字符集相同编码数值代表相同的字符时,则字符集 A 是字符集 B 的超集,或称字符集 B 是字符集 A 的子集。UTF8是ZHS16GBK的严格超集。对于子集到超集的转换,Oracle是允许的,但是对于超集到子集的转换是不允许的。
字符集一般遵循<language><bit size><encoding>的命名规则。比如AL16UTF16(AL指的是All Languages)。对于中文字符集ZHS16GBK,表示简体中文,一个字符需要16位比特,标准的字符集名称为GBK。
ORACLE支持的Unicode字符集最常用的是AL32UTF8,可以容纳多种语言文字;而只存储英文信息的数据库等来说,一般采用US7ASCII。
下文涉及到ORACLE三方面的字符集:数据库字符集、客户端字符集、客户端应用字符集。
ORACLE数据库字符集在创建后一般不能更改,创建数据库的过程中,一定要注意选择字符集。
对于简体中文平台,一般缺省的字符集是ZHS16GBK。此外,常见的中文字符集有ZHS16CGB231280(两者不相兼容)。
数据库字符集的相关文件在数据库上单独存贮在$ORACLE_HOME/nls/data。这些文件分别定义了语言(NLS_LANGUAGE)、区域(NLS_TERRITORY)和字符集(NLS_CHARCTERSET)。
利用EXP/IMP导数工具要注意客户端字符集的设置。客户端字符集通过设置NLS_LANG(language_territory.clients characterset)来完成。language指定客户端Oracle消息使用的语言、日期的显示;territory指定货币、数字等;而characterset控制客户端应用程序(比如sqlplus)使用的字符集,这个字符集对数据库传输的数据进行解码。
客户端字符集定义了客户端字符数据的编码方式,任何发自或发往客户端的字符数据均使用客户端定义的字符集编码,客户端可以看作是能与数据库直接连接的各种应用,例如 sqlplus,exp/imp 等。客户端字符集是通过设置 NLS_LANG参数来设定的。
NLS_LANG通常设置为和数据库字符集相同的字符集。这样导出的数据在导出端不发生转换,数据完整备份。导入的时候可以设置导入端NLS_LANG等于导出时的字符集,即使发生转换也发生一次。而转换也决定了导入的数据库字符集必须是导出的数据库字符集的超集,才能转换成功。
要识别导出文件的字符集,可以使用ultraedit工具或者cat xx.dmp | od -x | head -2查看文件头的第2、3个字节。常见的字符集有ZHS16GBK为0354;ZHS16CGB231280为0352;US7ASCII 为0001;UTF8 为0367等等。
数据库字符集通过NLS_DATABASE_PARAMETERS或者 select userenv('language') from dual查询;客户端字符集在 windows 平台下, 就是查询注册表NLS_LANG,而在 unix 平台下,就是环境变量 NLS_LANG;而客户端应用字符集可以通过cmd右键属性查看,决定查询在终端上的输出显示。一般为简体中文GBK字符集。
在oracle有关字符集的文档中,常见到有四个oracle参数,主要是前两个:
NLS_DATABASE_PARAMETERS来源于props$,是表示数据库的字符集。在创建数据库的时候设定的,一般不改变。
V$NLS_PARAMETERS显示数据库当前session ,受客户端影响(可能是alter session 或者环境变量或注册表或者参数文件);
NLS_INSTANCE_PARAMETE来源于v$parameter(表示客户端的字符集的设置,可能是参数文件,环境变量或者是注册表。);
NLS_SESSION_PARAMETERS有两种可能:既有可能显示由NLS_LANG 设置的参数,或着经过alter session 改变后的参数值(此时等同NLS_INSTANCE_PARAMETER);
--------------------------------------分割线 --------------------------------------
--------------------------------------分割线 --------------------------------------