代码改变世界

ORACLE字符集基础知识

2014-05-23 23:33  潇湘隐者  阅读(68599)  评论(2编辑  收藏  举报

概念描叙

   ORACLE数据库有国家字符集(national character set)与数据库字符集(database character set)之分。两者都是在创建数据库时需要设置的。国家字符集主要是用于NCHAR、NVARCHAR、NCLOB类型的字段数据,而数据库字符集使用很广泛,它用于:CHAR、VARCHAR、CLOB、LONG类型的字段数据;

   

   ORACLE的字符集名字一般由以下部分组成:语言或区域、表示一个字符的比特位数、标准字符集名称(可选项,S或C,表示服务器或客户端)。ORACLE字符集UTF8与UTFE不符合此规定,其它基本都是这种格式。NLS_LANG=<Language>_<Territory>.<Clients Characterset>

set nls_lang=AMERICAN_AMERICA.UTF8

set nls_lang=SIMPLIFIED CHINESE_AMERICA.UTF8

NLS( National Language Support)国家语言支持。NLS是数据库的一个非常强大的特性,它控制着数据的许多方面:比如数据如何存储,一般来说它控制着以下两个方面:

文本数据持久存储在磁盘上时如何编码

透明的将数据从一个字符集转换到另外一个字符集。

假设你在数据库中用WE8ISO8859P1 字符集存储8 位的数据,但是你的某些客户使用的是一种7 位字符集,如US7ASCII字符集转换过程通常会修改数据,而你往往会把一个较大的字符集(在此例中就是8 位字符集)映射到一个较小的字符集(此例中的7 位字符集)。这是一种有损转换(lossy conversion),字符就会被修改,这只是因为:较小的字符集不可能表示较大字符集中的每一个字符。但是这种转换必须发生。这也是乱码产生的原因。如果数据库以一种单字节字符集存储数据,但是客户(如一个Java 应用,因为Java 语言使用Unicode)希望数据采用多字节表示,就必须执行转换,只有这样客户应用才能使用这些数据。

ORACLE支持的Unicode字符集有以下几种,下面的列表给出了字符集的名称、对应的数据库版本范围、采用的Unicode的版本。

AL24UTFFSS:是ORACLE第一种支持Unicode的字符集,从7.2版本开始使用,但是它支持的Unicode版本为1.1,因此从9i开始就不支持此字符集了。

UTF8 : 是ORACLE从ORACLE8开始使用的属于UTF-8编码的字符集,从ORACLE8.0到ORACLE8.16,Unicode版本为2.1,而ORACLE817到10g,采用的Unicode标 准为3.0

UTFE :用于EBCDIC码平台上的数据库Unicode字符集。因此它属于专用系统使用的字符集,其它属性与UTF8基本相同。

AL32UTF8 :是从ORACLE9开始使用的属于UTF-8编码的字符集,与UTF8相比,它采用的Unicode版本更新,在10g版本中使用的是Unicode 4.01标准,而UTF8因 为兼容性的考虑,在10g版本中用的是Unicode 3.0标准。

AL16UTF16:是ORACLE第一种采用UTF-16编码方式的字符集,从ORACLE9开始使用,是作为缺省的国家字符集使用,它不能被用作数据库的字符集。这是因为数 据库的字符集决定了SQL与PL/SQL源码的编码方式,对于UTF-16这种使用固定的两个字节来表示英文字母的编码方案来说,确实不适于用作数据库 的字符集,ORACLE目前采用的数据库字符集都是基于ASCII或EBCDID作为子集的编码方案。

对于US7ASCII,表示区域是US,用7个比特位表示一个字符,标准的字符集名称为ASCII。

对于中文字符集ZHS16GBK,表示简体中文(ZHT为繁体中文),一个字符需要16位比特,标准的字符集名称为GBK。而ZHS16CGB231280表示简体中文,一个字符需要16位比特,标准的字符集名称为GB231280,属于我们前面提过的1981年发布的GB2312-80标准。虽然我们说,GBK编码标准是GB2312编码标准的扩展,但是数据库字符集ZHS16GBK与ZHS16CGB231280之间却不是严格的超集与子集的关系,主要是有些汉字的编码在两个字符集中的数值是不同的,因此它们进行字符集转换时会出现问题。

查看字符集参数

1:查看NLS_CHARACTERSET:字符集,NLS_NCHAR_CHARACTERSET:国家字符集

实例字符集环境

SELECT * FROM NLS_INSTANCE_PARAMETERS

主要涉及NLS_LANGUAGE、NLS_TERRITORY的值. NLS_INSTANCE_PARAMETERS其来源于v$parameter,注意:网上很多资料都说"NLS_INSTANCE_PARAMETERS 表示客户端的字符集的设置,可以是参数文件,环境变量或者是注册表",而且网上都人人亦云。记住它是表示实例的字符集环境。

数据库可用字符集参数设置

SELECT * FROM V$NLS_VALID_VALUES

数据库服务器字符集

SELECT * FROM NLS_DATABASE_PARAMETERS

 

NLS_DATABASE_PARAMETERS其来源于props$,是表示数据库的字符集。

clip_image002

客户端字符集环境

SELECT * FROM V$NLS_PARAMETERS;

SELECT USERENV('language') FROM DUAL;

USERENV、 V$NLS_PARAMETERS表示当前字符集环境。如果你在客户端执行,则表示客户端字符集环境。

会话字符集环境

SELECT * FROM NLS_SESSION_PARAMETERS;

它来源于v$nls_parameters,表示会话自己的设置,可能是会话的环境变量或者是ALTER SESSION完成,如果会话没有特殊的设置,将与 V$NLS_PARAMETERS一致。

2: 查看客户端字符集(NLS_LANG) 的方法

如果系统是LINUX或UNIX平台,则也可以通过下面命令查看(前提是必须设置了NLS_LANG,否则查出来的是空值)

[etl@m1 ~]$env | grep NLS_LANG

NLS_LANG=AMERICAN_AMERICA.ZHS16GBK

[etl@m1 ~]$echo $NLS_LANG

AMERICAN_AMERICA.ZHS16GBK

如果系统是WINDOWS平台,则可以通过下面命令查看:

1:在运行里面,输入regedit进入注册表,HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraDb11g_home1\里面(最后一项与实例名、数据库版本有关系),找到NLS_LANG选项,双击它,你就可以看到相应的值。

2:echo %NLS_LANG% 。如果没有设置NLS_LANG,用这个命令看不到相关信息。

3: 设置NLS_LANG的方法

Windows平台:

3.1

set NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK

set NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK

3.2 可以通过修改注册表键值永久设置

HKEY_LOCAL_MACHINE/SOFTWARE/ORACLE/KEY_XXXX_home1/NLS_LANG

UNIX & LINUX

3.3

export NLS_LANG=AMERICAN_AMERICA.UTF8

3.4可以编辑 bash_profile 文件进行永久设置

vi .bash_profile

export NLS_LANG="SIMPLIFIED CHINESE_CHINA.ZHS16GBK"

客户端的字符集要求与服务器一致,才能正确显示数据库的非Ascii字符。如果多个设置存在的时候优先级关系为:SQL Function >Alter session>环境变量>注册表>参数文件 字符集要求一致,但是语言设置却可以不同,语言设置建议用英文。如字符集是zhs16gbk,则nls_lang可以是American_America.zhs16gbk。

修改数据库字符集

数据库字符集在创建后原则上不能更改。因此,在前期规划和安装之初考虑使用哪一种字符集十分重要。对数据库服务器而言,错误的修改字符集将会导致很多不可测的后果,可能会严重影响数据库的正常运行,所以在修改之前一定要确认两种字符集是否存在子集和超集的关系。一般来说,除非万不得已,我们不建议修改ORACLE数据库SERVER端的字符集。

有两种方法修改数据库字符集设置

1. 通常需要导出数据库数据,重建数据库,然后再导入数据库数据的方式来转换。

2. 通过ALTER DATABASE CHARACTER SET语句修改字符集,但创建数据库后可以修改的字符集是有限制的,只有新的字符集是当前字符集的超集时才能修改数据库字符集,例如UTF8是US7ASCII的超集,修改数据库字符集可使用ALTER DATABASE CHARACTER SET UTF8。

特别说明,我们最常用的两种字符集ZHS16GBK和ZHS16CGB231280之间不存在子集和超集关系,因此理论上讲这两种字符集之间的相互转换不受支持修改

关于数据库子集-超级对照表(subset-superset pairs),可以参考官方文档,例如ORACLE 10g的http://docs.oracle.com/cd/B19306_01/server.102/b14225/applocaledata.htm

Table A-11 Subset-Superset Pairs

Subset

Superset

AR8ADOS710

AR8ADOS710T

AR8ADOS720

AR8ADOS720T

AR8ADOS720T

AR8ADOS720

AR8APTEC715

AR8APTEC715T

AR8ARABICMACT

AR8ARABICMAC

AR8ISO8859P6

AR8ASMO708PLUS

AR8ISO8859P6

AR8ASMO8X

AR8MUSSAD768

AR8MUSSAD768T

AR8MUSSAD768T

AR8MUSSAD768

AR8NAFITHA711

AR8NAFITHA711T

AR8NAFITHA721

AR8NAFITHA721T

AR8SAKHR707

AR8SAKHR707T

AR8SAKHR707T

AR8SAKHR707

BLT8CP921

BLT8ISO8859P13

BLT8CP921

LT8MSWIN921

D7DEC

D7SIEMENS9780X

D7SIEMENS9780X

D7DEC

DK7SIEMENS9780X

N7SIEMENS9780X

I7DEC

I7SIEMENS9780X

I7SIEMENS9780X

IW8EBCDIC424

IW8EBCDIC424

IW8EBCDIC1086

KO16KSC5601

KO16MSWIN949

LT8MSWIN921

BLT8ISO8859P13

LT8MSWIN921

BLT8CP921

N7SIEMENS9780X

DK7SIEMENS9780X

US7ASCII

See Table A-12, "US7ASCII Supersets".

UTF8

AL32UTF8

WE8DEC

TR8DEC

WE8DEC

WE8NCR4970

WE8ISO8859P1

WE8MSWIN1252

WE8ISO8859P9

TR8MSWIN1254

WE8NCR4970

TR8DEC

WE8NCR4970

WE8DEC

WE8PC850

WE8PC858

   1: SQL>CONN / AS SYSDBA;
   2:  
   3: SQL>SHUTDOWN IMMEDIATE;
   4:  
   5: SQL>STARTUP MOUNT;
   6:  
   7: SQL>ALTER SYSTEM ENABLE RESTRICTED SESSION;
   8:  
   9: SQL>ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
  10:  
  11: SQL>ALTER SYSTEM SET AQ_TM_PROCESSES=0;
  12:  
  13: SQL>ALTER DATABASE OPEN;

--可以从子集到父集

   1: SQL>ALTER DATABASE CHARACTER SET ZHS16GBK;
   2:  
   3: --如果是从父集到子集,需要使用INTERNAL_USE参数,跳过超子集检测
   4:  
   5: SQL>ALTER DATABASE NATIONAL CHARACTER SET UTF8;
   6:  
   7: --SQL>ALTER DATABASE NATIONAL CHARACTER SET INTERNAL_USE UTF8;
   8:  
   9: SQL>SHUTDOWN IMMEDIATE;
  10:  
  11: SQL>STARTUP;

ALTER DATABASE NATIONAL CHARACTER SET UTF8;

有可能会出现ORA-12717: Cannot ALTER DATABASE NATIONAL CHARACTER SET when NCLOB data exists 这样的提示信息.这时你用ALTER DATABASE NATIONAL CHARACTER SET INTERNAL_USE UTF8;就可解决上述问题。

参考资料:

      http://blog.csdn.net/jkl_123/article/details/6157379

       http://blog.csdn.net/tianlesoftware/article/details/4915223