3.3 字符集文件及字符支持

Oracle的全球支持是通过Oracle NLS Runtime Library(NLSRTL)来实施的,NLS运行库通过独立的函数来完成运行时和语言相关的转换及控制。字符集相关的文件在数据库服务器上是单独存储的,这些文件的位置受环境变量参数 ORA_NLS*参数的控制,在不同版本中,这个环境变量的参数并不相同,在Oracle 7.2中,这个环境变量是ORA_NLS;在Oracle 7.3中,这个环境变量值变更为ORA_NLS32;在Oracle8/Oracle8i/Oracle 9i的各个版本中,该环境变量为ORA_NLS33;在Oracle 10g中,该环境变量参数又变更为ORA_NLS10。通常缺省地,可以不设置这个变量。

在Oracle 9i中,这个参数指向的字符文件缺省位置为$ORACLE_HOME/ocommon/nls/ admin/data。在Oracle 10g/11g中,这个参数指向的字符文件缺省位置为$ORACLE_HOME/ nls/data。

该目录下存放3类文件分别用来定义语言(NLS_LANGUAGE)、区域(NLS_TERRITORY)和字符集(NLS_CHARACTERSET),其中中文语言的文件为lx00023.nlb,如图3-2所示。

用Oracle提供的Locale Builder工具打开该文件,就可以看到在中文语言环境下的相关设置,如月份、星期等,如图3-3所示。

当然最终要得文件是字符集文件,用 Locale Builder 工具打开相关的字符集文件(ZHS16GBK字符集文件为lx20354.nlb),如图3-4所示,就可以看到和字符集相关的设置信息。

图3-2 选择语言文件

图 3-3 月份和星期格式

通过字符集文件,Oracle 将所有汉字编码存放在数据库之中,这样当存放和转换汉字时才有了依据,我们看一下字符编码,如图3-5所示。

图3-4 打开字符集文件

图3-5 字符编码

在上图中可以看到,汉字“盖”的编码为0xb8c7,这也就是Oracle在数据库中存放汉字时的编码,有了这个编码方案,Oracle才能知道在一个字符集中,字符0xb8c7真正代表什么:

SQL> select dump('盖') from dual;

DUMP('盖')

---------------------

Typ=96 Len=2: 184,199

SQL> select concat(to_char(184,'xx'),to_char(199,'xx')) from dual;

CONCAT

------

b8 c7

这个过程完全可逆,在同样字符集的数据库中,可以进行如下转换:

SQL> select to_number('b8c7','xxxxxx') from dual;

TO_NUMBER('B8C7','XXXXXX')

--------------------------

47303

SQL> select chr(47303) from dual;

CH

--

通过以上介绍可以知道这些字符文件非常重要,如果这个字符文件丢失或损坏,则数据库将会出现故障。在Windows系统上做一个简单的测试:

C:\oracle\10.2.0\nls\data>dir lx20354.nlb

2006-10-10 14:52   477,772 lx20354.nlb

C:\oracle\10.2.0\nls\data>move lx20354.nlb lx20354.nlb.b

C:\oracle\10.2.0\nls\data>net start oracleserviceeygle

OracleServiceEYGLE 服务正在启动 ...

OracleServiceEYGLE 服务已经启动成功。

C:\oracle\10.2.0\nls\data>sqlplus "/ as sysdba"

Error 5 initializing SQL*Plus

NLS initialization error

以上测试显示,当字符集文件被移除之后,由于不能正常读取字符集文件,SQL*Plus已经不能正常登录,此时可以修改NLS_LANG参数设置其他字符集,使得SQL*Plus可以完成初始化:

C:\oracle\10.2.0\nls\data>set nls_lang=AMERICAN_AMERICA.US7ASCII

C:\oracle\10.2.0\nls\data>sqlplus "/ as sysdba"

SQL*Plus: Release 10.2.0.3.0 - Production on Mon Jun 18 17:10:46 2007

Copyright (c) 1982, 2006, Oracle. All Rights Reserved.

ERROR:

ORA-03113: end-of-file on communication channel

此时SQL*Plus可以执行,但是无法登录数据库,这是因为SQL*Plus执行时就需要调用字符集文件,在Linux系统下,可以通过系统命令strace跟踪到这些调用行为。

以下命令通过strace命令将SQL*Plus的调用过程跟踪写入sqlplus.log文件:

[oracle@wapdb ~]$ strace -o sqlplus.log sqlplus /nolog

SQL*Plus: Release 11.1.0.6.0 - Production on Mon Sep 27 10:23:52 2010

Copyright (c) 1982, 2007, Oracle. All rights reserved.

SQL> exit

过滤一下跟踪文件,可以得到SQL*Plus启动依次调用的字符文件:

[oracle@wapdb ~]$ grep nls sqlplus.log

open("/opt/oracle/product/11.1.0/nls/data/lx1boot.nlb", O_RDONLY) = 3

open("/opt/oracle/product/11.1.0/nls/data/lx00001.nlb", O_RDONLY) = 3

open("/opt/oracle/product/11.1.0/nls/data/lx20354.nlb", O_RDONLY) = 3

open("/opt/oracle/product/11.1.0/nls/data/lx10035.nlb", O_RDONLY) = 3

open("/opt/oracle/product/11.1.0/nls/data/lx20001.nlb", O_RDONLY) = 3

open("/opt/oracle/product/11.1.0/nls/data/lx40001.nlb", O_RDONLY) = 3

open("/opt/oracle/product/11.1.0/nls/data/lx10001.nlb", O_RDONLY) = 8

注意以上调用中lx1boot.nlb是字符集的初始化文件,而lx20354.nlb正是SQL*Plus软件启动时需要调用的ZHS16GBK字符集文件。如果没有了字符集文件,应用软件(包括SQL*Plus和Oracle执行软件)都是无法完成初始化的。