码迷,mamicode.com
首页 > 数据库 > 详细

oracle字符集

时间:2016-01-29 21:28:40      阅读:398      评论:0      收藏:0      [点我收藏+]

标签:oracle、字符集

 

                       oracle字符集

1、引言

ORACLE数据库字符集,即Oracle全球化支持(Globalization Support),或即国家语言支持(NLS)其作用是用本国语言和格式来存储、处理和检索数据。利用全球化支持,ORACLE为用户提供自己熟悉的数据库母语环境,诸如日期格式、数字格式和存储序列等。Oracle可以支持多种语言及字符集,其中oracle8i支持48种语言、76个国家地域、229种字符集,而oracle9i则支持57种语言、88个国家地域、235种字符集。

2、概述

2.1字符集概述

实质就是按照一定的字符编码方案,对一组特定的符号,分别赋予不同数值编码的集合。Oracle数据库最早支持的编码方案是US7ASCII。

    Oracle 的字符集命名遵循以下命名规则 :

即:  <语言><比特位数><编码 >

例:NLS_LANG=AMERICAN_AMERICA.ZHS16GBK

比如: ZHS16GBK表示采用GBK编码格式、16位(两个字节)简体中文字符集

2.2字符集超级

当一种字符集(字符集A)的编码数值包含所有另一种字符集(字符集B)的编码数值,并且两种字符集相同编码数值代表相同的字符时,则字符集A是字符集B的超级,或称字符集B是字符集A的子集。

    Oracle8i 和oracle9i官方文档资料中备有子集-超级对照表(subset-superset pairs),例如:WE8ISO8859P1是WE8MSWIN1252的子集。由于US7ASCII是最早的Oracle数据库编码格式,因此有许多字符集是US7ASCII的超集,例如WE8ISO8859P1、ZHS16CGB231280、ZHS16GBK都是US7ASCII的超集。

2.3oracle数据库字符集

数据库字符集在创建数据库时指定,在创建后通常不能更改。在创建数据库时,可以指定字符集(CHARACTER SET)和国家字符集(NATIONAL CHARACTERSET)。

2.3.1 字符集

  • 用来存储CHAR, VARCHAR2,CLOB, LONG等类型数据

  • 用来标示诸如表名、列名以及PL/SQL变量等

  • 用来存储SQL和PL/SQL程序单元等

  • 国家字符集

  • 用以存储NCHAR, NVARCHAR2,NCLOB等类型数据

  • 国家字符集实质上是为oracle选择的附加字符集,主要作用是为了增强oracle的字符处理能力,因为NCHAR数据类型可以提供对亚洲使用定长多字节编码的支持,而数据库字符集则不能。国家字符集在oracle9i中进行了重新定义,只能在unicode编码中的AF16UTF16和UTF8中选择,默认值是 AF16UTF16

  • 查询字符集参数

    可以查询以下数据字典或视图查看字符集设置情况

    nls_database_parameters 、props$、 v$nls_parameters

    查询结果中NLS_CHARACTERSET表示字符集,NLS_NCHAR_CHARACTERSET表示国家字符集

2.3.4 修改数据库字符集

    按照上文所说,数据库字符集在创建后原则上不能更改。如果需要修改字符集,通常需要导出数据库数据,重建数据库,再导入数据库数据的方式来转换,或通过ALTER DATABASE CHARACTER SET语句修改字符集,但创建数据库后修改字符集是有限制的,只有新的字符集是当前字符集的超集时才能修改数据库字符集,例如UTF8是US7ASCII的超集,修改数据库字符集可使用ALTER DATABASE CHARACTER SET UTF8。

2.3.5 常见字符集乱码问题

  • 使用客户端sqlplus向数据库存储数据

这个过程存在3个字符集设置:

    (1)客户端应用字符集

    (2)客户端NLS_LANG参数设置

    (3)服务器端数据库字符集(Character Set)设置

    客户端应用sqlplus中能够显示什么样的字符取决于客户端操作系统语言环境(客户端应用字符集),但在应用中录入这些字符后,这些字符能否在数据库中正常存储,还与另外两个字符集设置紧密相关,其中客户端NLS_LANG参数主要用于字符数据传输过程中的转换判断。

    乱码产生是由于几个字符集之间转换不匹配造成,分以下几种情况:

    (注:字符集之间如果不存在子集、超集对应关系时的情况不予考虑,因为这种情况下字符集之间转换必产生乱码)   

 1)服务器端数据库字符集与客户端应用字符集相同,与客户端NLS_LANG参数设置不同

    如果客户端NLS_LANG字符集是其它两种字符集的子集,转换过程将出现乱码。

    解决方法:将三种字符集设置成同一字符集,或NLS_LANG字符集是其它两种字符集的超集

2 )服务器端数据库字符集与客户端NLS_LANG参数设置相同,与客户端应用字符集不同

    如果客户端应用字符集是其它两种字符集的超集时,转换过程将出现乱码

3 )客户端应用字符集、客户端NLS_LANG参数设置、服务器端数据库字符集互不相同

    此种情况较为复杂,但三种字符集之间只要有不能转换的字符,则必产生乱码

  

常见的乱码大致有两种情形:

    (1)汉字变成问号“?”;

当从字符集A 转换成字符集B时,如果转换字符之间不存在对应关系,NLS_LANG使用替代字符“?”替代无法映射的字符;

    (2)汉字变成未知字符(虽然有些是汉字,但与原字符含义不同)

转换存在对应关系,但字符集A 中的字符编码与字符集B 中的字符编码代表不同含义。

  • 导入/导出过程

这个过程存在4个字符集设置:

   (1)源数据库字符集

   (2)EXP过程中NLS_LANG参数

   (3)IMP过程中NLS_LANG参数

   (4)目标数据库字符集

    出现乱码原因

    1 )当源数据库字符集不等于EXP过程中NLS_LANG参数,且源数据库字符集是EXP过程中NLS_LANG的子集,才能保证导出文件正确,其他情况则导出文件字符乱码

    2 )EXP过程中NLS_LANG字符集不等于IMP过程中NLS_LANG字符集,且EXP过程中NLS_LANG字符集是IMP过程中NLS_LANG字符集的子级,才能保证第一次转换正常,否则第一次转换中出现乱码。

    3 )如果第一次转换正常,IMP过程中NLS_LANG字符集是目标数据库字符集的子集或相同,才能保证第二次转换正常,否则则第二次转换中出现乱码。

3、现状分析

对目前实施数据库资源池的几个试点网省进行字符集统计

 

字符集

数量

占比

AL32UTF8

15

17.86%

UTF8

20

23.81%

WE8MSWIN1252

1

1.19%

ZHS16GBK

45

53.57%

空白

3

3.57%

合计

84


 

以上为试点网省目前在运行oracle数据库抽检的共84套,其中字符集ZHS16GBK和UTF8 两种共占比约77.38%。由于字符集多样,存在国网公司向网省公司下发数据时存在无法写入的问题及网省内不同数据库迁移出现乱码问题。

4、风险后果

  • 可能出现数据库数据混乱的情况。

  • 可能会出现char、varchar2、LOB等字段长度不够,需要重新定义表结构。

  • 可能会造成数据库表char、varchar2、CLOBLONG字段出现乱码。

  • 可能会损坏数据文件,丢失数据。

  • 操作系统和数据库服务器字符集不兼容,存入服务器里数据错误而不易察觉。

  • 不能存入一些特殊的符号。

 

5、解决建议

数据库字符集在创建后原则上不能更改。因此,在设计和安装之初考虑使用哪一种字符集十分重要。对数据库server而言,错误的修改字符集将会导致很多不可测的后果,可能会严重影响数据库的正常运行,所以在修改之前一定要确认两种字符集是否存在子集和超集的关系。一般来说,除非万不得已,我们不建议修改oracle数据库server端的字符集。特别说明,我们最常用的两种字符集ZHS16GBK和Al32UTF8之间不存在子集和超集关系,因此理论上讲这两种字符集之间的相互转换不受支持。

为了避免字符集不统一,先制定以下几点建议:

  • 对于新系统,严格按照国网统一标准的字符集;

  • 对于旧系统,如果字符集是国网统一标准的字符集或者子集,可以修改保持统一;

  • 对于旧系统,不是国网统一标准的字符集及子集,ZHS16GBK可以转换为AL32UTF8,在迁移过程中,客户端随便为其中的一种编码,迁移数据不会出现乱码,但是会出现列长度不够现象,反之则不行;

  • 对于其他字符集,为了避免在数据库迁移过程中由于字符集不同导致的数据损失,oracle提供了字符集扫描工具(character set scanner),通过这个工具我们可以测试在数据迁移过程中由于字符集转换可能带来的问题,然后根据测试结果,确定数据迁移过程中最佳字符集解决方案。

修改数据库字符集有以下方法:

5.1 从子集修改到超集

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

5.2 修改dmp文件

dmp文件的第2第3字节记录了字符集信息,因此直接修改dmp文件的第2第3字节的内容就可以‘骗’过oracle的检查。这样做理论上也仅是从子集到超集可以修改,但很多情况下在没有子集和超集关系的情况下也可以修改,我们常用的一些字符集,如US7ASCII,WE8ISO8859P1,ZHS16CGB231280,ZHS16GBK基本都可以改。因为改的只是dmp文件,所以影响不大。

具体的修改方法比较多,最简单的就是直接用UltraEdit修改dmp文件的第2和第3个字节。

比如想将dmp文件的字符集改为ZHS16GBK,可以用以下SQL查出该种字符集对应的16进制代码:SQL> select to_char(nls_charset_id(‘ZHS16GBK‘), ‘xxxx‘) from dual;

0354

然后将dmp文件的2、3字节修改为0354即可。

5.3 epx/imp修改字符集

需要导出数据库数据,重建数据库,再导入数据库数据的方式来转换

  • 备份数据库中所有用户的数据

  • 评估转换成后的风险(使用csscan工具)

  • 更改数据库的字符集或创建新数据库

  • 导入备份的用户数据

注意:转换之前,要使用Oracle的csscan工具对数据库扫描,评估字符集转换前后,数据有可能的损坏情况,如果评估乐观,可以进行转换尝试,但是没有任何专家建议这种做,即使是在试验的数据库上,无外乎“安全”二字;如果评估情况糟糕,那就绝对要放弃了。

 

 

 

                         

 


oracle字符集

标签:oracle、字符集

原文地址:http://lanniao.blog.51cto.com/7717032/1739812

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!